aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJulien Lancelot <julien.lancelot@sonarsource.com>2015-10-05 12:55:35 +0200
committerJulien Lancelot <julien.lancelot@sonarsource.com>2015-10-05 15:39:00 +0200
commita3caa98f84849143fa78f9fc286079e871b3c9dd (patch)
tree4deec6bf15632e570e10b35e6df5cd7340025017
parentbce3d38e9c99e156a8251f95cb437f3d54ee9a80 (diff)
downloadsonarqube-a3caa98f84849143fa78f9fc286079e871b3c9dd.tar.gz
sonarqube-a3caa98f84849143fa78f9fc286079e871b3c9dd.zip
SONAR-6397 Do not read SCM info from db on first analysis
-rw-r--r--server/sonar-server-benchmarks/src/test/java/org/sonar/server/benchmark/PersistFileSourcesStepTest.java7
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/computation/analysis/AnalysisMetadataHolder.java5
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/computation/analysis/MutableAnalysisMetadataHolder.java5
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/computation/analysis/ReportAnalysisMetadataHolder.java15
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/computation/scm/ScmInfoRepositoryImpl.java20
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/computation/step/BuildComponentTreeStep.java14
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/computation/analysis/MutableAnalysisMetadataHolderRule.java10
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/computation/analysis/ReportAnalysisMetadataHolderTest.java51
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/computation/scm/ScmInfoRepositoryImplTest.java34
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/computation/step/BuildComponentTreeStepTest.java38
-rw-r--r--sonar-db/src/main/java/org/sonar/db/component/SnapshotDao.java4
-rw-r--r--sonar-db/src/main/java/org/sonar/db/component/SnapshotMapper.java2
-rw-r--r--sonar-db/src/main/resources/org/sonar/db/component/SnapshotMapper.xml9
-rw-r--r--sonar-db/src/test/java/org/sonar/db/component/SnapshotDaoTest.java9
-rw-r--r--sonar-db/src/test/resources/org/sonar/db/component/SnapshotDaoTest/has_last_snapshot_by_component_uuid.xml48
15 files changed, 250 insertions, 21 deletions
diff --git a/server/sonar-server-benchmarks/src/test/java/org/sonar/server/benchmark/PersistFileSourcesStepTest.java b/server/sonar-server-benchmarks/src/test/java/org/sonar/server/benchmark/PersistFileSourcesStepTest.java
index 87ad097dbab..09520d5b788 100644
--- a/server/sonar-server-benchmarks/src/test/java/org/sonar/server/benchmark/PersistFileSourcesStepTest.java
+++ b/server/sonar-server-benchmarks/src/test/java/org/sonar/server/benchmark/PersistFileSourcesStepTest.java
@@ -37,6 +37,7 @@ import org.sonar.batch.protocol.output.BatchReportWriter;
import org.sonar.core.util.Uuids;
import org.sonar.db.DbClient;
import org.sonar.db.DbTester;
+import org.sonar.server.computation.analysis.MutableAnalysisMetadataHolderRule;
import org.sonar.server.computation.batch.BatchReportDirectoryHolderImpl;
import org.sonar.server.computation.batch.BatchReportReaderImpl;
import org.sonar.server.computation.batch.TreeRootHolderRule;
@@ -69,6 +70,9 @@ public class PersistFileSourcesStepTest {
@Rule
public TreeRootHolderRule treeRootHolder = new TreeRootHolderRule();
+ @Rule
+ public MutableAnalysisMetadataHolderRule analysisMetadataHolder = new MutableAnalysisMetadataHolderRule();
+
@Test
public void benchmark() throws Exception {
File reportDir = prepareReport();
@@ -85,7 +89,8 @@ public class PersistFileSourcesStepTest {
batchReportDirectoryHolder.setDirectory(reportDir);
org.sonar.server.computation.batch.BatchReportReader batchReportReader = new BatchReportReaderImpl(batchReportDirectoryHolder);
SourceService sourceService = new SourceService(dbClient, null);
- ScmInfoRepositoryImpl scmInfoRepository = new ScmInfoRepositoryImpl(batchReportReader, dbClient, sourceService);
+ analysisMetadataHolder.setIsFirstAnalysis(false);
+ ScmInfoRepositoryImpl scmInfoRepository = new ScmInfoRepositoryImpl(batchReportReader, analysisMetadataHolder, dbClient, sourceService);
PersistFileSourcesStep step = new PersistFileSourcesStep(dbClient, System2.INSTANCE, treeRootHolder, batchReportReader,
new SourceLinesRepositoryImpl(batchReportReader), scmInfoRepository);
step.execute();
diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/analysis/AnalysisMetadataHolder.java b/server/sonar-server/src/main/java/org/sonar/server/computation/analysis/AnalysisMetadataHolder.java
index 5653e72110f..445fd8a63c8 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/computation/analysis/AnalysisMetadataHolder.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/computation/analysis/AnalysisMetadataHolder.java
@@ -26,4 +26,9 @@ public interface AnalysisMetadataHolder {
* @throws IllegalStateException if no analysis date has been set
*/
Date getAnalysisDate();
+
+ /**
+ * @throws IllegalStateException if isFirstAnalysis has not been set
+ */
+ boolean isFirstAnalysis();
}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/analysis/MutableAnalysisMetadataHolder.java b/server/sonar-server/src/main/java/org/sonar/server/computation/analysis/MutableAnalysisMetadataHolder.java
index aa8736419ea..1733010fc93 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/computation/analysis/MutableAnalysisMetadataHolder.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/computation/analysis/MutableAnalysisMetadataHolder.java
@@ -27,4 +27,9 @@ public interface MutableAnalysisMetadataHolder extends AnalysisMetadataHolder {
* @throws IllegalStateException if the analysis date has already been set
*/
void setAnalysisDate(Date date);
+
+ /**
+ * @throws IllegalStateException if isFirstAnalysis has already been set
+ */
+ void setIsFirstAnalysis(boolean isFirstAnalysis);
}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/analysis/ReportAnalysisMetadataHolder.java b/server/sonar-server/src/main/java/org/sonar/server/computation/analysis/ReportAnalysisMetadataHolder.java
index fa1fdf3754b..64e4c923d0a 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/computation/analysis/ReportAnalysisMetadataHolder.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/computation/analysis/ReportAnalysisMetadataHolder.java
@@ -28,6 +28,9 @@ public class ReportAnalysisMetadataHolder implements MutableAnalysisMetadataHold
@CheckForNull
private Long analysisDate;
+ @CheckForNull
+ private Boolean firstAnalysis;
+
@Override
public void setAnalysisDate(Date date) {
checkState(analysisDate == null, "Analysis date has already been set");
@@ -39,4 +42,16 @@ public class ReportAnalysisMetadataHolder implements MutableAnalysisMetadataHold
checkState(analysisDate != null, "Analysis date has not been set");
return new Date(this.analysisDate);
}
+
+ @Override
+ public void setIsFirstAnalysis(boolean firstAnalysis) {
+ checkState(this.firstAnalysis == null, "firstAnalysis flag has already been set");
+ this.firstAnalysis = firstAnalysis;
+ }
+
+ @Override
+ public boolean isFirstAnalysis() {
+ checkState(firstAnalysis != null, "firstAnalysis flag has not been set");
+ return firstAnalysis;
+ }
}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/scm/ScmInfoRepositoryImpl.java b/server/sonar-server/src/main/java/org/sonar/server/computation/scm/ScmInfoRepositoryImpl.java
index 20a7e1d88b9..b39fc819f20 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/computation/scm/ScmInfoRepositoryImpl.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/computation/scm/ScmInfoRepositoryImpl.java
@@ -28,6 +28,7 @@ import org.sonar.batch.protocol.output.BatchReport;
import org.sonar.db.DbClient;
import org.sonar.db.DbSession;
import org.sonar.db.protobuf.DbFileSources;
+import org.sonar.server.computation.analysis.AnalysisMetadataHolder;
import org.sonar.server.computation.batch.BatchReportReader;
import org.sonar.server.computation.component.Component;
import org.sonar.server.source.SourceService;
@@ -39,13 +40,15 @@ public class ScmInfoRepositoryImpl implements ScmInfoRepository {
private static final Logger LOGGER = Loggers.get(ScmInfoRepositoryImpl.class);
private final BatchReportReader batchReportReader;
+ private final AnalysisMetadataHolder analysisMetadataHolder;
private final DbClient dbClient;
private final SourceService sourceService;
private final Map<Component, ScmInfo> scmInfoCache = new HashMap<>();
- public ScmInfoRepositoryImpl(BatchReportReader batchReportReader, DbClient dbClient, SourceService sourceService) {
+ public ScmInfoRepositoryImpl(BatchReportReader batchReportReader, AnalysisMetadataHolder analysisMetadataHolder, DbClient dbClient, SourceService sourceService) {
this.batchReportReader = batchReportReader;
+ this.analysisMetadataHolder = analysisMetadataHolder;
this.dbClient = dbClient;
this.sourceService = sourceService;
}
@@ -68,15 +71,17 @@ public class ScmInfoRepositoryImpl implements ScmInfoRepository {
private Optional<ScmInfo> getScmInfoForComponent(Component component) {
BatchReport.Changesets changesets = batchReportReader.readChangesets(component.getReportAttributes().getRef());
if (changesets == null) {
- LOGGER.trace("Reading SCM info from db for file '{}'", component);
return getScmInfoFromDb(component);
- } else {
- LOGGER.trace("Reading SCM info from report for file '{}'", component);
- return Optional.<ScmInfo>of(new ReportScmInfo(changesets));
}
+ return getScmInfoFromReport(component, changesets);
}
private Optional<ScmInfo> getScmInfoFromDb(Component component) {
+ if (analysisMetadataHolder.isFirstAnalysis()) {
+ return Optional.absent();
+ }
+ LOGGER.trace("Reading SCM info from db for file '{}'", component);
+
DbSession dbSession = dbClient.openSession(false);
try {
Optional<Iterable<DbFileSources.Line>> linesOpt = sourceService.getLines(dbSession, component.getUuid(), 1, Integer.MAX_VALUE);
@@ -88,4 +93,9 @@ public class ScmInfoRepositoryImpl implements ScmInfoRepository {
dbClient.closeSession(dbSession);
}
}
+
+ private static Optional<ScmInfo> getScmInfoFromReport(Component component, BatchReport.Changesets changesets) {
+ LOGGER.trace("Reading SCM info from report for file '{}'", component);
+ return Optional.<ScmInfo>of(new ReportScmInfo(changesets));
+ }
}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/step/BuildComponentTreeStep.java b/server/sonar-server/src/main/java/org/sonar/server/computation/step/BuildComponentTreeStep.java
index 6e1e2a2fdc5..036bce963f4 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/computation/step/BuildComponentTreeStep.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/computation/step/BuildComponentTreeStep.java
@@ -28,6 +28,7 @@ import javax.annotation.Nullable;
import org.sonar.batch.protocol.output.BatchReport;
import org.sonar.core.component.ComponentKeys;
import org.sonar.db.DbClient;
+import org.sonar.db.DbSession;
import org.sonar.server.computation.analysis.MutableAnalysisMetadataHolder;
import org.sonar.server.computation.batch.BatchReportReader;
import org.sonar.server.computation.component.Component;
@@ -62,7 +63,18 @@ public class BuildComponentTreeStep implements ComputationStep {
String branch = reportMetadata.hasBranch() ? reportMetadata.getBranch() : null;
BatchReport.Component reportProject = reportReader.readComponent(reportMetadata.getRootComponentRef());
UuidFactory uuidFactory = new UuidFactory(dbClient, moduleKey(reportProject, branch));
- treeRootHolder.setRoot(new ComponentRootBuilder(reportProject, uuidFactory, branch).build());
+ Component project = new ComponentRootBuilder(reportProject, uuidFactory, branch).build();
+ treeRootHolder.setRoot(project);
+ setIsFirstAnalysis(project.getUuid());
+ }
+
+ private void setIsFirstAnalysis(String projectUuid){
+ DbSession dbSession = dbClient.openSession(false);
+ try {
+ analysisMetadataHolder.setIsFirstAnalysis(!dbClient.snapshotDao().hasLastSnapshotByComponentUuid(dbSession, projectUuid));
+ } finally {
+ dbClient.closeSession(dbSession);
+ }
}
private class ComponentRootBuilder {
diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/analysis/MutableAnalysisMetadataHolderRule.java b/server/sonar-server/src/test/java/org/sonar/server/computation/analysis/MutableAnalysisMetadataHolderRule.java
index dd06019d1d9..ba6984f58cc 100644
--- a/server/sonar-server/src/test/java/org/sonar/server/computation/analysis/MutableAnalysisMetadataHolderRule.java
+++ b/server/sonar-server/src/test/java/org/sonar/server/computation/analysis/MutableAnalysisMetadataHolderRule.java
@@ -39,4 +39,14 @@ public class MutableAnalysisMetadataHolderRule extends ExternalResource implemen
public void setAnalysisDate(Date date) {
delegate.setAnalysisDate(date);
}
+
+ @Override
+ public boolean isFirstAnalysis() {
+ return delegate.isFirstAnalysis();
+ }
+
+ @Override
+ public void setIsFirstAnalysis(boolean isFirstAnalysis) {
+ delegate.setIsFirstAnalysis(isFirstAnalysis);
+ }
}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/analysis/ReportAnalysisMetadataHolderTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/analysis/ReportAnalysisMetadataHolderTest.java
index d9d6cf93c3b..c5b362d9eee 100644
--- a/server/sonar-server/src/test/java/org/sonar/server/computation/analysis/ReportAnalysisMetadataHolderTest.java
+++ b/server/sonar-server/src/test/java/org/sonar/server/computation/analysis/ReportAnalysisMetadataHolderTest.java
@@ -33,14 +33,6 @@ public class ReportAnalysisMetadataHolderTest {
private Date someDate = new Date();
@Test
- public void getAnalysisDate_throws_ISE_when_not_holder_is_not_initialized() {
- expectedException.expect(IllegalStateException.class);
- expectedException.expectMessage("Analysis date has not been set");
-
- new ReportAnalysisMetadataHolder().getAnalysisDate();
- }
-
- @Test
public void getAnalysisDate_returns_date_with_same_time_as_the_one_set_with_setAnalysisDate() throws InterruptedException {
ReportAnalysisMetadataHolder underTest = new ReportAnalysisMetadataHolder();
@@ -54,6 +46,14 @@ public class ReportAnalysisMetadataHolderTest {
}
@Test
+ public void getAnalysisDate_throws_ISE_when_holder_is_not_initialized() {
+ expectedException.expect(IllegalStateException.class);
+ expectedException.expectMessage("Analysis date has not been set");
+
+ new ReportAnalysisMetadataHolder().getAnalysisDate();
+ }
+
+ @Test
public void setAnalysisDate_throws_ISE_when_called_twice() {
expectedException.expect(IllegalStateException.class);
expectedException.expectMessage("Analysis date has already been set");
@@ -63,4 +63,39 @@ public class ReportAnalysisMetadataHolderTest {
underTest.setAnalysisDate(someDate);
underTest.setAnalysisDate(someDate);
}
+
+ @Test
+ public void isFirstAnalysis_return_true() throws Exception {
+ ReportAnalysisMetadataHolder underTest = new ReportAnalysisMetadataHolder();
+
+ underTest.setIsFirstAnalysis(true);
+ assertThat(underTest.isFirstAnalysis()).isTrue();
+ }
+
+ @Test
+ public void isFirstAnalysis_return_false() throws Exception {
+ ReportAnalysisMetadataHolder underTest = new ReportAnalysisMetadataHolder();
+
+ underTest.setIsFirstAnalysis(false);
+ assertThat(underTest.isFirstAnalysis()).isFalse();
+ }
+
+ @Test
+ public void isFirstAnalysis_throws_ISE_when_holder_is_not_initialized() {
+ expectedException.expect(IllegalStateException.class);
+ expectedException.expectMessage("firstAnalysis flag has not been set");
+
+ new ReportAnalysisMetadataHolder().isFirstAnalysis();
+ }
+
+ @Test
+ public void setIsFirstAnalysis_throws_ISE_when_called_twice() {
+ expectedException.expect(IllegalStateException.class);
+ expectedException.expectMessage("firstAnalysis flag has already been set");
+
+ ReportAnalysisMetadataHolder underTest = new ReportAnalysisMetadataHolder();
+
+ underTest.setIsFirstAnalysis(true);
+ underTest.setIsFirstAnalysis(true);
+ }
}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/scm/ScmInfoRepositoryImplTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/scm/ScmInfoRepositoryImplTest.java
index 6108f9f640d..6380d274b2c 100644
--- a/server/sonar-server/src/test/java/org/sonar/server/computation/scm/ScmInfoRepositoryImplTest.java
+++ b/server/sonar-server/src/test/java/org/sonar/server/computation/scm/ScmInfoRepositoryImplTest.java
@@ -30,6 +30,7 @@ import org.sonar.db.DbClient;
import org.sonar.db.DbTester;
import org.sonar.db.protobuf.DbFileSources;
import org.sonar.db.source.FileSourceDto;
+import org.sonar.server.computation.analysis.MutableAnalysisMetadataHolderRule;
import org.sonar.server.computation.batch.BatchReportReaderRule;
import org.sonar.server.computation.component.Component;
import org.sonar.server.source.SourceService;
@@ -41,27 +42,32 @@ import static org.sonar.server.computation.component.ReportComponent.builder;
public class ScmInfoRepositoryImplTest {
- @Rule
- public LogTester logTester = new LogTester();
+ static final int FILE_REF = 1;
+
+ static final Component FILE = builder(Component.Type.FILE, FILE_REF).setKey("FILE_KEY").setUuid("FILE_UUID").build();
@Rule
public ExpectedException thrown = ExpectedException.none();
- static final int FILE_REF = 1;
- static final Component FILE = builder(Component.Type.FILE, FILE_REF).setKey("FILE_KEY").setUuid("FILE_UUID").build();
+ @Rule
+ public LogTester logTester = new LogTester();
@Rule
public BatchReportReaderRule reportReader = new BatchReportReaderRule();
@Rule
+ public MutableAnalysisMetadataHolderRule analysisMetadataHolder = new MutableAnalysisMetadataHolderRule();
+
+ @Rule
public DbTester dbTester = DbTester.create(System2.INSTANCE);
DbClient dbClient = dbTester.getDbClient();
- ScmInfoRepositoryImpl underTest = new ScmInfoRepositoryImpl(reportReader, dbClient, new SourceService(dbClient, null));
+ ScmInfoRepositoryImpl underTest = new ScmInfoRepositoryImpl(reportReader, analysisMetadataHolder, dbClient, new SourceService(dbClient, null));
@Test
public void read_from_report() throws Exception {
+ analysisMetadataHolder.setIsFirstAnalysis(false);
addChangesetInReport("john", 123456789L, "rev-1");
ScmInfo scmInfo = underTest.getScmInfo(FILE).get();
@@ -72,6 +78,7 @@ public class ScmInfoRepositoryImplTest {
@Test
public void read_from_db() throws Exception {
+ analysisMetadataHolder.setIsFirstAnalysis(false);
addChangesetInDb("henry", 123456789L, "rev-1");
ScmInfo scmInfo = underTest.getScmInfo(FILE).get();
@@ -82,6 +89,7 @@ public class ScmInfoRepositoryImplTest {
@Test
public void read_from_report_even_if_data_in_db_exists() throws Exception {
+ analysisMetadataHolder.setIsFirstAnalysis(false);
addChangesetInDb("henry", 123456789L, "rev-1");
addChangesetInReport("john", 1234567810L, "rev-2");
@@ -96,11 +104,13 @@ public class ScmInfoRepositoryImplTest {
@Test
public void return_nothing_when_no_data_in_report_and_db() throws Exception {
+ analysisMetadataHolder.setIsFirstAnalysis(false);
assertThat(underTest.getScmInfo(FILE)).isAbsent();
}
@Test
- public void return_nothing_when_nothing_in_erpot_and_db_has_no_scm() throws Exception {
+ public void return_nothing_when_nothing_in_report_and_db_has_no_scm() throws Exception {
+ analysisMetadataHolder.setIsFirstAnalysis(false);
DbFileSources.Data.Builder fileDataBuilder = DbFileSources.Data.newBuilder();
fileDataBuilder.addLinesBuilder()
.setLine(1);
@@ -114,6 +124,8 @@ public class ScmInfoRepositoryImplTest {
@Test
public void fail_with_NPE_when_component_is_null() throws Exception {
+ analysisMetadataHolder.setIsFirstAnalysis(false);
+
thrown.expect(NullPointerException.class);
thrown.expectMessage("Component cannot be bull");
@@ -122,6 +134,7 @@ public class ScmInfoRepositoryImplTest {
@Test
public void load_scm_info_from_cache_when_already_read() throws Exception {
+ analysisMetadataHolder.setIsFirstAnalysis(false);
addChangesetInReport("john", 123456789L, "rev-1");
ScmInfo scmInfo = underTest.getScmInfo(FILE).get();
assertThat(scmInfo.getAllChangesets()).hasSize(1);
@@ -133,6 +146,15 @@ public class ScmInfoRepositoryImplTest {
assertThat(logTester.logs(TRACE)).isEmpty();
}
+ @Test
+ public void not_read_in_db_on_first_analysis() throws Exception {
+ analysisMetadataHolder.setIsFirstAnalysis(true);
+ addChangesetInDb("henry", 123456789L, "rev-1");
+
+ assertThat(underTest.getScmInfo(FILE)).isAbsent();
+ assertThat(logTester.logs(TRACE)).isEmpty();
+ }
+
private void addChangesetInDb(String author, Long date, String revision) {
DbFileSources.Data.Builder fileDataBuilder = DbFileSources.Data.newBuilder();
fileDataBuilder.addLinesBuilder()
diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/step/BuildComponentTreeStepTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/step/BuildComponentTreeStepTest.java
index 788507d9197..c085483ace5 100644
--- a/server/sonar-server/src/test/java/org/sonar/server/computation/step/BuildComponentTreeStepTest.java
+++ b/server/sonar-server/src/test/java/org/sonar/server/computation/step/BuildComponentTreeStepTest.java
@@ -38,6 +38,7 @@ import org.sonar.batch.protocol.output.BatchReport.Metadata;
import org.sonar.db.DbClient;
import org.sonar.db.DbTester;
import org.sonar.db.component.ComponentDto;
+import org.sonar.db.component.SnapshotDto;
import org.sonar.server.computation.analysis.MutableAnalysisMetadataHolderRule;
import org.sonar.server.computation.batch.BatchReportReaderRule;
import org.sonar.server.computation.component.Component;
@@ -53,6 +54,7 @@ import static org.sonar.db.component.ComponentTesting.newDirectory;
import static org.sonar.db.component.ComponentTesting.newFileDto;
import static org.sonar.db.component.ComponentTesting.newModuleDto;
import static org.sonar.db.component.ComponentTesting.newProjectDto;
+import static org.sonar.db.component.SnapshotTesting.newSnapshotForProject;
@Category(DbTests.class)
@RunWith(DataProviderRunner.class)
@@ -274,6 +276,36 @@ public class BuildComponentTreeStepTest {
verifyComponent(FILE_1_REF, REPORT_MODULE_KEY + ":" + REPORT_FILE_KEY_1, "DEFG");
}
+ @Test
+ public void set_first_analysis_to_true_when_no_snapshot() throws Exception {
+ reportReader.putComponent(componentWithKey(ROOT_REF, PROJECT, REPORT_PROJECT_KEY));
+ underTest.execute();
+
+ assertThat(analysisMetadataHolder.isFirstAnalysis()).isTrue();
+ }
+
+ @Test
+ public void set_first_analysis_to_true_when_no_last_snapshot() throws Exception {
+ ComponentDto project = insertComponent(newProjectDto("ABCD").setKey(REPORT_PROJECT_KEY));
+ insertSnapshot(newSnapshotForProject(project).setLast(false));
+
+ reportReader.putComponent(componentWithKey(ROOT_REF, PROJECT, REPORT_PROJECT_KEY));
+ underTest.execute();
+
+ assertThat(analysisMetadataHolder.isFirstAnalysis()).isTrue();
+ }
+
+ @Test
+ public void set_first_analysis_to_false_when_last_snapshot_exist() throws Exception {
+ ComponentDto project = insertComponent(newProjectDto("ABCD").setKey(REPORT_PROJECT_KEY));
+ insertSnapshot(newSnapshotForProject(project).setLast(true));
+
+ reportReader.putComponent(componentWithKey(ROOT_REF, PROJECT, REPORT_PROJECT_KEY));
+ underTest.execute();
+
+ assertThat(analysisMetadataHolder.isFirstAnalysis()).isFalse();
+ }
+
private void verifyComponent(Component component, Component.Type type, int componentRef, int size) {
assertThat(component.getType()).isEqualTo(type);
assertThat(component.getReportAttributes().getRef()).isEqualTo(componentRef);
@@ -342,4 +374,10 @@ public class BuildComponentTreeStepTest {
return component;
}
+ private SnapshotDto insertSnapshot(SnapshotDto snapshot) {
+ dbClient.snapshotDao().insert(dbTester.getSession(), snapshot);
+ dbTester.getSession().commit();
+ return snapshot;
+ }
+
}
diff --git a/sonar-db/src/main/java/org/sonar/db/component/SnapshotDao.java b/sonar-db/src/main/java/org/sonar/db/component/SnapshotDao.java
index 46306bf9a04..55d3fbbb630 100644
--- a/sonar-db/src/main/java/org/sonar/db/component/SnapshotDao.java
+++ b/sonar-db/src/main/java/org/sonar/db/component/SnapshotDao.java
@@ -53,6 +53,10 @@ public class SnapshotDao implements Dao {
return mapper(session).selectLastSnapshot(componentId);
}
+ public boolean hasLastSnapshotByComponentUuid(DbSession session, String componentUUid) {
+ return mapper(session).countLastSnapshotByComponentUuid(componentUUid) > 0;
+ }
+
public List<SnapshotDto> selectSnapshotsByComponentId(DbSession session, long componentId) {
return mapper(session).selectSnapshotsByQuery(new SnapshotQuery().setComponentId(componentId));
}
diff --git a/sonar-db/src/main/java/org/sonar/db/component/SnapshotMapper.java b/sonar-db/src/main/java/org/sonar/db/component/SnapshotMapper.java
index 49fe34a0ee0..a77633f7d1a 100644
--- a/sonar-db/src/main/java/org/sonar/db/component/SnapshotMapper.java
+++ b/sonar-db/src/main/java/org/sonar/db/component/SnapshotMapper.java
@@ -34,6 +34,8 @@ public interface SnapshotMapper {
@CheckForNull
SnapshotDto selectLastSnapshot(Long resourceId);
+ int countLastSnapshotByComponentUuid(String componentUuid);
+
List<SnapshotDto> selectSnapshotsByQuery(@Param("query") SnapshotQuery query);
List<SnapshotDto> selectPreviousVersionSnapshots(@Param(value = "componentId") Long componentId, @Param(value = "lastVersion") String lastVersion);
diff --git a/sonar-db/src/main/resources/org/sonar/db/component/SnapshotMapper.xml b/sonar-db/src/main/resources/org/sonar/db/component/SnapshotMapper.xml
index 6892b27e3b6..01b89c7e1aa 100644
--- a/sonar-db/src/main/resources/org/sonar/db/component/SnapshotMapper.xml
+++ b/sonar-db/src/main/resources/org/sonar/db/component/SnapshotMapper.xml
@@ -56,6 +56,15 @@
where s.islast=${_true} and s.project_id = #{resource}
</select>
+ <select id="countLastSnapshotByComponentUuid" resultType="Integer">
+ SELECT count(s.id)
+ FROM snapshots s
+ INNER JOIN projects p ON p.id=s.project_id AND p.uuid=#{componentUuid}
+ <where>
+ AND s.islast=${_true}
+ </where>
+ </select>
+
<select id="selectSnapshotsByQuery" parameterType="map" resultType="Snapshot">
SELECT
<include refid="snapshotColumns"/>
diff --git a/sonar-db/src/test/java/org/sonar/db/component/SnapshotDaoTest.java b/sonar-db/src/test/java/org/sonar/db/component/SnapshotDaoTest.java
index 4377a7d45ca..9768a52e1c6 100644
--- a/sonar-db/src/test/java/org/sonar/db/component/SnapshotDaoTest.java
+++ b/sonar-db/src/test/java/org/sonar/db/component/SnapshotDaoTest.java
@@ -261,6 +261,15 @@ public class SnapshotDaoTest {
assertThat(isLast).isFalse();
}
+ @Test
+ public void has_last_snapshot_by_component_uuid() throws Exception {
+ db.prepareDbUnit(getClass(), "has_last_snapshot_by_component_uuid.xml");
+
+ assertThat(underTest.hasLastSnapshotByComponentUuid(db.getSession(), "ABCD")).isTrue();
+ assertThat(underTest.hasLastSnapshotByComponentUuid(db.getSession(), "EFGH")).isFalse();
+ assertThat(underTest.hasLastSnapshotByComponentUuid(db.getSession(), "FGHI")).isFalse();
+ }
+
private static SnapshotDto defaultSnapshot() {
return new SnapshotDto()
.setComponentId(3L)
diff --git a/sonar-db/src/test/resources/org/sonar/db/component/SnapshotDaoTest/has_last_snapshot_by_component_uuid.xml b/sonar-db/src/test/resources/org/sonar/db/component/SnapshotDaoTest/has_last_snapshot_by_component_uuid.xml
new file mode 100644
index 00000000000..16f7fe75471
--- /dev/null
+++ b/sonar-db/src/test/resources/org/sonar/db/component/SnapshotDaoTest/has_last_snapshot_by_component_uuid.xml
@@ -0,0 +1,48 @@
+<dataset>
+
+ <!-- Has last snapshot -->
+ <projects id="1" root_id="[null]" scope="PRJ" qualifier="TRK" kee="org.struts:struts" name="Struts"
+ uuid="ABCD" project_uuid="ABCD" module_uuid="[null]" module_uuid_path="."
+ description="the description" long_name="Apache Struts"
+ enabled="[true]" language="[null]" copy_resource_id="[null]" person_id="[null]" path="[null]" authorization_updated_at="[null]" />
+ <snapshots id="1" project_id="1" parent_snapshot_id="[null]" root_project_id="1" root_snapshot_id="[null]"
+ status="P" islast="[true]" purge_status="[null]"
+ period1_mode="[null]" period1_param="[null]" period1_date="[null]"
+ period2_mode="[null]" period2_param="[null]" period2_date="[null]"
+ period3_mode="[null]" period3_param="[null]" period3_date="[null]"
+ period4_mode="[null]" period4_param="[null]" period4_date="[null]"
+ period5_mode="[null]" period5_param="[null]" period5_date="[null]"
+ depth="[null]" scope="PRJ" qualifier="TRK" created_at="1228222680000" build_date="1228222680000"
+ version="[null]" path=""/>
+ <snapshots id="10" project_id="1" parent_snapshot_id="[null]" root_project_id="1" root_snapshot_id="[null]"
+ status="P" islast="[false]" purge_status="[null]"
+ period1_mode="[null]" period1_param="[null]" period1_date="[null]"
+ period2_mode="[null]" period2_param="[null]" period2_date="[null]"
+ period3_mode="[null]" period3_param="[null]" period3_date="[null]"
+ period4_mode="[null]" period4_param="[null]" period4_date="[null]"
+ period5_mode="[null]" period5_param="[null]" period5_date="[null]"
+ depth="[null]" scope="PRJ" qualifier="TRK" created_at="1228136280000" build_date="1228136280000"
+ version="[null]" path=""/>
+
+ <!-- No snapshot -->
+ <projects id="2" root_id="1" kee="org.struts:struts-core" name="Struts Core"
+ uuid="EFGH" project_uuid="ABCD" module_uuid="[null]" module_uuid_path=".ABCD."
+ scope="PRJ" qualifier="BRC" long_name="Struts Core"
+ description="[null]" enabled="[true]" language="[null]" copy_resource_id="[null]" person_id="[null]" authorization_updated_at="[null]" />
+
+ <!-- No last snapshot -->
+ <projects id="3" root_id="1" kee="org.struts:struts-data" name="Struts Data"
+ uuid="FGHI" project_uuid="ABCD" module_uuid="EFGH" module_uuid_path=".ABCD.EFGH."
+ scope="PRJ" qualifier="BRC" long_name="Struts Data"
+ description="[null]" enabled="[true]" language="[null]" copy_resource_id="[null]" person_id="[null]" authorization_updated_at="[null]" />
+ <snapshots id="3" project_id="3" parent_snapshot_id="2" root_project_id="1" root_snapshot_id="1"
+ status="P" islast="[false]" purge_status="[null]"
+ period1_mode="[null]" period1_param="[null]" period1_date="[null]"
+ period2_mode="[null]" period2_param="[null]" period2_date="[null]"
+ period3_mode="[null]" period3_param="[null]" period3_date="[null]"
+ period4_mode="[null]" period4_param="[null]" period4_date="[null]"
+ period5_mode="[null]" period5_param="[null]" period5_date="[null]"
+ depth="[null]" scope="PRJ" qualifier="BRC" created_at="1228222680000" build_date="1228222680000"
+ version="[null]" path="1.2."/>
+
+</dataset>