aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJulien HENRY <julien.henry@sonarsource.com>2015-03-26 14:09:31 +0100
committerTeryk Bellahsene <teryk.bellahsene@sonarsource.com>2015-03-26 17:32:20 +0100
commit6f5449b6daa0f588c2e18bf5e04e1dbe5b2688b1 (patch)
treefc9986467f08ae2afad9f8825b1de80fd0a0c2af
parenta83dfe19c1da637994148d538e116d4edf22ed98 (diff)
downloadsonarqube-6f5449b6daa0f588c2e18bf5e04e1dbe5b2688b1.tar.gz
sonarqube-6f5449b6daa0f588c2e18bf5e04e1dbe5b2688b1.zip
SONAR-6317 Feed SCM in compute report - batch side
-rw-r--r--plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/timemachine/AbstractNewCoverageFileAnalyzer.java36
-rw-r--r--plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/timemachine/NewCoverageFileAnalyzer.java13
-rw-r--r--plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/timemachine/NewItCoverageFileAnalyzer.java9
-rw-r--r--plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/timemachine/NewOverallCoverageFileAnalyzer.java9
-rw-r--r--plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/timemachine/NewCoverageFileAnalyzerTest.java156
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/batch/ProjectRepositoryLoader.java3
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/computation/issue/SourceLinesCache.java31
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/platform/ServerComponents.java2
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/source/SourceService.java38
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/source/ws/ScmAction.java92
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/source/ws/ScmWriter.java67
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/source/ws/SourcesWs.java5
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/source/SourceServiceTest.java48
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/source/ws/HashActionTest.java1
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/source/ws/IndexActionTest.java4
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/source/ws/LinesActionTest.java9
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/source/ws/RawActionTest.java2
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/source/ws/ScmActionTest.java83
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/source/ws/ScmWriterTest.java73
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/source/ws/ShowActionTest.java2
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/source/ws/SourcesWsTest.java13
-rw-r--r--sonar-batch-protocol/src/main/java/org/sonar/batch/protocol/input/FileData.java23
-rw-r--r--sonar-batch-protocol/src/test/java/org/sonar/batch/protocol/input/ProjectRepositoriesTest.java7
-rw-r--r--sonar-batch-protocol/src/test/resources/org/sonar/batch/protocol/input/ProjectRepositoriesTest/testToJson.json6
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/index/DefaultIndex.java6
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/index/ResourceCache.java6
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/index/SourceDataFactory.java76
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/mediumtest/BatchMediumTester.java2
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/report/PublishReportJob.java50
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/repository/ProjectScmRepositoryLoader.java155
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/scan/ProjectReactorReady.java21
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/scan/ProjectScanContainer.java11
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/scm/DefaultBlameOutput.java63
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/scm/ScmSensor.java72
-rw-r--r--sonar-batch/src/test/java/org/sonar/batch/index/SourceDataFactoryTest.java67
-rw-r--r--sonar-batch/src/test/java/org/sonar/batch/mediumtest/preview/IncrementalModeMediumTest.java2
-rw-r--r--sonar-batch/src/test/java/org/sonar/batch/mediumtest/scm/ScmMediumTest.java143
-rw-r--r--sonar-batch/src/test/java/org/sonar/batch/qualitygate/QualityGateVerifierTest.java6
-rw-r--r--sonar-batch/src/test/java/org/sonar/batch/report/PublishReportJobTest.java17
-rw-r--r--sonar-batch/src/test/java/org/sonar/batch/scan/ProjectReactorReadyTest.java6
-rw-r--r--sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/StatusDetectionTest.java4
-rw-r--r--sonar-batch/src/test/java/org/sonar/batch/scm/DefaultBlameOutputTest.java4
-rw-r--r--sonar-plugin-api/src/test/java/org/sonar/api/resources/CoreMetricsTest.java2
43 files changed, 505 insertions, 940 deletions
diff --git a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/timemachine/AbstractNewCoverageFileAnalyzer.java b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/timemachine/AbstractNewCoverageFileAnalyzer.java
index 1ade50dfc61..1ac4c1a4f3a 100644
--- a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/timemachine/AbstractNewCoverageFileAnalyzer.java
+++ b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/timemachine/AbstractNewCoverageFileAnalyzer.java
@@ -19,15 +19,10 @@
*/
package org.sonar.plugins.core.timemachine;
-import org.sonar.batch.components.Period;
-
-import org.sonar.batch.components.TimeMachineConfiguration;
-import org.sonar.api.batch.RequiresDB;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import org.apache.commons.lang.ObjectUtils;
import org.sonar.api.batch.*;
-import org.sonar.api.measures.CoreMetrics;
import org.sonar.api.measures.Measure;
import org.sonar.api.measures.Metric;
import org.sonar.api.resources.Project;
@@ -35,6 +30,13 @@ import org.sonar.api.resources.Qualifiers;
import org.sonar.api.resources.Resource;
import org.sonar.api.resources.Scopes;
import org.sonar.api.utils.KeyValueFormat;
+import org.sonar.batch.components.Period;
+import org.sonar.batch.components.TimeMachineConfiguration;
+import org.sonar.batch.index.ResourceCache;
+import org.sonar.batch.protocol.output.BatchReport.Scm;
+import org.sonar.batch.protocol.output.BatchReport.Scm.Changeset;
+import org.sonar.batch.protocol.output.BatchReportReader;
+import org.sonar.batch.report.PublishReportJob;
import javax.annotation.Nullable;
@@ -50,16 +52,20 @@ import java.util.Map;
@DependedUpon(DecoratorBarriers.END_OF_TIME_MACHINE)
public abstract class AbstractNewCoverageFileAnalyzer implements Decorator {
- private List<PeriodStruct> structs;
+ private final List<PeriodStruct> structs;
+ private final PublishReportJob publishReportJob;
+ private final ResourceCache resourceCache;
- public AbstractNewCoverageFileAnalyzer(TimeMachineConfiguration timeMachineConfiguration) {
- structs = Lists.newArrayList();
+ public AbstractNewCoverageFileAnalyzer(TimeMachineConfiguration timeMachineConfiguration, PublishReportJob publishReportJob, ResourceCache resourceCache) {
+ this(Lists.<PeriodStruct>newArrayList(), publishReportJob, resourceCache);
for (Period period : timeMachineConfiguration.periods()) {
structs.add(new PeriodStruct(period.getIndex(), period.getDate()));
}
}
- AbstractNewCoverageFileAnalyzer(List<PeriodStruct> structs) {
+ AbstractNewCoverageFileAnalyzer(List<PeriodStruct> structs, PublishReportJob publishReportJob, ResourceCache resourceCache) {
+ this.resourceCache = resourceCache;
+ this.publishReportJob = publishReportJob;
this.structs = structs;
}
@@ -89,8 +95,7 @@ public abstract class AbstractNewCoverageFileAnalyzer implements Decorator {
@DependsUpon
public List<Metric> dependsOnMetrics() {
- return Arrays.asList(CoreMetrics.SCM_LAST_COMMIT_DATETIMES_BY_LINE,
- getCoverageLineHitsDataMetric(), getConditionsByLineMetric(), getCoveredConditionsByLineMetric());
+ return Arrays.asList(getCoverageLineHitsDataMetric(), getConditionsByLineMetric(), getCoveredConditionsByLineMetric());
}
@DependedUpon
@@ -112,11 +117,11 @@ public abstract class AbstractNewCoverageFileAnalyzer implements Decorator {
}
private boolean parse(DecoratorContext context) {
- Measure lastCommits = context.getMeasure(CoreMetrics.SCM_LAST_COMMIT_DATETIMES_BY_LINE);
+ BatchReportReader reader = new BatchReportReader(publishReportJob.getReportDir());
+ Scm componentScm = reader.readComponentScm(resourceCache.get(context.getResource()).batchId());
Measure hitsByLineMeasure = context.getMeasure(getCoverageLineHitsDataMetric());
- if (lastCommits != null && lastCommits.hasData() && hitsByLineMeasure != null && hitsByLineMeasure.hasData()) {
- Map<Integer, Date> datesByLine = KeyValueFormat.parseIntDateTime(lastCommits.getData());
+ if (componentScm != null && hitsByLineMeasure != null && hitsByLineMeasure.hasData()) {
Map<Integer, Integer> hitsByLine = parseCountByLine(hitsByLineMeasure);
Map<Integer, Integer> conditionsByLine = parseCountByLine(context.getMeasure(getConditionsByLineMetric()));
Map<Integer, Integer> coveredConditionsByLine = parseCountByLine(context.getMeasure(getCoveredConditionsByLineMetric()));
@@ -128,7 +133,8 @@ public abstract class AbstractNewCoverageFileAnalyzer implements Decorator {
int hits = entry.getValue();
int conditions = (Integer) ObjectUtils.defaultIfNull(conditionsByLine.get(lineId), 0);
int coveredConditions = (Integer) ObjectUtils.defaultIfNull(coveredConditionsByLine.get(lineId), 0);
- Date date = datesByLine.get(lineId);
+ Changeset changeset = componentScm.getChangeset(componentScm.getChangesetIndexByLine(lineId - 1));
+ Date date = changeset.hasDate() ? new Date(changeset.getDate()) : null;
for (PeriodStruct struct : structs) {
struct.analyze(date, hits, conditions, coveredConditions);
}
diff --git a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/timemachine/NewCoverageFileAnalyzer.java b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/timemachine/NewCoverageFileAnalyzer.java
index 352070ccc68..38aac00f0ea 100644
--- a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/timemachine/NewCoverageFileAnalyzer.java
+++ b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/timemachine/NewCoverageFileAnalyzer.java
@@ -19,21 +19,22 @@
*/
package org.sonar.plugins.core.timemachine;
-import org.sonar.batch.components.TimeMachineConfiguration;
-
import org.sonar.api.measures.CoreMetrics;
import org.sonar.api.measures.Metric;
+import org.sonar.batch.components.TimeMachineConfiguration;
+import org.sonar.batch.index.ResourceCache;
+import org.sonar.batch.report.PublishReportJob;
import java.util.List;
public class NewCoverageFileAnalyzer extends AbstractNewCoverageFileAnalyzer {
- public NewCoverageFileAnalyzer(TimeMachineConfiguration timeMachineConfiguration) {
- super(timeMachineConfiguration);
+ public NewCoverageFileAnalyzer(TimeMachineConfiguration timeMachineConfiguration, PublishReportJob publishReportJob, ResourceCache resourceCache) {
+ super(timeMachineConfiguration, publishReportJob, resourceCache);
}
- NewCoverageFileAnalyzer(List<PeriodStruct> structs) {
- super(structs);
+ NewCoverageFileAnalyzer(List<PeriodStruct> structs, PublishReportJob publishReportJob, ResourceCache resourceCache) {
+ super(structs, publishReportJob, resourceCache);
}
@Override
diff --git a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/timemachine/NewItCoverageFileAnalyzer.java b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/timemachine/NewItCoverageFileAnalyzer.java
index 2dbcf8416a4..48222f59ce2 100644
--- a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/timemachine/NewItCoverageFileAnalyzer.java
+++ b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/timemachine/NewItCoverageFileAnalyzer.java
@@ -19,15 +19,16 @@
*/
package org.sonar.plugins.core.timemachine;
-import org.sonar.batch.components.TimeMachineConfiguration;
-
import org.sonar.api.measures.CoreMetrics;
import org.sonar.api.measures.Metric;
+import org.sonar.batch.components.TimeMachineConfiguration;
+import org.sonar.batch.index.ResourceCache;
+import org.sonar.batch.report.PublishReportJob;
public class NewItCoverageFileAnalyzer extends AbstractNewCoverageFileAnalyzer {
- public NewItCoverageFileAnalyzer(TimeMachineConfiguration timeMachineConfiguration) {
- super(timeMachineConfiguration);
+ public NewItCoverageFileAnalyzer(TimeMachineConfiguration timeMachineConfiguration, PublishReportJob publishReportJob, ResourceCache resourceCache) {
+ super(timeMachineConfiguration, publishReportJob, resourceCache);
}
@Override
diff --git a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/timemachine/NewOverallCoverageFileAnalyzer.java b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/timemachine/NewOverallCoverageFileAnalyzer.java
index b57db6dbe0e..75a1a83686c 100644
--- a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/timemachine/NewOverallCoverageFileAnalyzer.java
+++ b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/timemachine/NewOverallCoverageFileAnalyzer.java
@@ -19,15 +19,16 @@
*/
package org.sonar.plugins.core.timemachine;
-import org.sonar.batch.components.TimeMachineConfiguration;
-
import org.sonar.api.measures.CoreMetrics;
import org.sonar.api.measures.Metric;
+import org.sonar.batch.components.TimeMachineConfiguration;
+import org.sonar.batch.index.ResourceCache;
+import org.sonar.batch.report.PublishReportJob;
public class NewOverallCoverageFileAnalyzer extends AbstractNewCoverageFileAnalyzer {
- public NewOverallCoverageFileAnalyzer(TimeMachineConfiguration timeMachineConfiguration) {
- super(timeMachineConfiguration);
+ public NewOverallCoverageFileAnalyzer(TimeMachineConfiguration timeMachineConfiguration, PublishReportJob publishReportJob, ResourceCache resourceCache) {
+ super(timeMachineConfiguration, publishReportJob, resourceCache);
}
@Override
diff --git a/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/timemachine/NewCoverageFileAnalyzerTest.java b/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/timemachine/NewCoverageFileAnalyzerTest.java
index 8ef3f98c1bb..af6d25828a6 100644
--- a/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/timemachine/NewCoverageFileAnalyzerTest.java
+++ b/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/timemachine/NewCoverageFileAnalyzerTest.java
@@ -19,13 +19,23 @@
*/
package org.sonar.plugins.core.timemachine;
+import org.junit.Before;
+import org.junit.Rule;
import org.junit.Test;
+import org.junit.rules.TemporaryFolder;
import org.mockito.ArgumentMatcher;
import org.sonar.api.batch.DecoratorContext;
import org.sonar.api.measures.CoreMetrics;
import org.sonar.api.measures.Measure;
import org.sonar.api.measures.Metric;
+import org.sonar.api.resources.File;
+import org.sonar.api.resources.Resource;
import org.sonar.api.utils.DateUtils;
+import org.sonar.batch.index.ResourceCache;
+import org.sonar.batch.protocol.output.BatchReport.Scm;
+import org.sonar.batch.protocol.output.BatchReport.Scm.Changeset;
+import org.sonar.batch.protocol.output.BatchReportWriter;
+import org.sonar.batch.report.PublishReportJob;
import java.text.ParseException;
import java.text.SimpleDateFormat;
@@ -35,28 +45,57 @@ import java.util.List;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.argThat;
-import static org.mockito.Mockito.*;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
public class NewCoverageFileAnalyzerTest {
+ @Rule
+ public TemporaryFolder temp = new TemporaryFolder();
+
+ private DecoratorContext context;
+ private NewCoverageFileAnalyzer decorator;
+ private BatchReportWriter writer;
+
+ @Before
+ public void prepare() throws Exception {
+ context = mock(DecoratorContext.class);
+ Resource f = File.create("src/Foo.java").setEffectiveKey("foo:src/Foo.java");
+ when(context.getResource()).thenReturn(f);
+ ResourceCache cache = new ResourceCache();
+ cache.add(f, null);
+ List<AbstractNewCoverageFileAnalyzer.PeriodStruct> structs = Arrays.asList(
+ new AbstractNewCoverageFileAnalyzer.PeriodStruct(1, newDate("2009-12-25")),
+ new AbstractNewCoverageFileAnalyzer.PeriodStruct(3, newDate("2011-02-18")));
+ PublishReportJob publishReportJob = mock(PublishReportJob.class);
+ java.io.File reportBaseDir = temp.newFolder();
+ when(publishReportJob.getReportDir()).thenReturn(reportBaseDir);
+ writer = new BatchReportWriter(reportBaseDir);
+ decorator = new NewCoverageFileAnalyzer(structs, publishReportJob, cache);
+
+ }
+
@Test
public void shouldDoNothingIfNoScmData() throws ParseException {
- DecoratorContext context = mock(DecoratorContext.class);
when(context.getMeasure(CoreMetrics.COVERAGE_LINE_HITS_DATA))
.thenReturn(new Measure(CoreMetrics.COVERAGE_LINE_HITS_DATA, "1=10"));
- NewCoverageFileAnalyzer decorator = newDecorator();
decorator.doDecorate(context);
verify(context, never()).saveMeasure(any(Measure.class));
}
@Test
public void shouldDoNothingIfNoCoverageData() throws ParseException {
- DecoratorContext context = mock(DecoratorContext.class);
- when(context.getMeasure(CoreMetrics.SCM_LAST_COMMIT_DATETIMES_BY_LINE))
- .thenReturn(new Measure(CoreMetrics.SCM_LAST_COMMIT_DATETIMES_BY_LINE, "10=2008-05-18T00:00:00+0000"));
+ writer.writeComponentScm(Scm.newBuilder()
+ .setComponentRef(1)
+ .addChangeset(Changeset.newBuilder()
+ .setDate(DateUtils.parseDateTime("2008-05-18T00:00:00+0000").getTime())
+ .build())
+ .addChangesetIndexByLine(0)
+ .build());
- NewCoverageFileAnalyzer decorator = newDecorator();
decorator.doDecorate(context);
verify(context, never()).saveMeasure(any(Measure.class));
@@ -64,13 +103,31 @@ public class NewCoverageFileAnalyzerTest {
@Test
public void shouldGetNewLines() throws ParseException {
- DecoratorContext context = mock(DecoratorContext.class);
when(context.getMeasure(CoreMetrics.COVERAGE_LINE_HITS_DATA)).thenReturn(
new Measure(CoreMetrics.COVERAGE_LINE_HITS_DATA, "10=2;11=3"));
- when(context.getMeasure(CoreMetrics.SCM_LAST_COMMIT_DATETIMES_BY_LINE)).thenReturn(
- new Measure(CoreMetrics.SCM_LAST_COMMIT_DATETIMES_BY_LINE, "10=2007-01-15T00:00:00+0000;11=2011-01-01T00:00:00+0000"));
+ writer.writeComponentScm(Scm.newBuilder()
+ .setComponentRef(1)
+ .addChangeset(Changeset.newBuilder()
+ .build())
+ .addChangeset(Changeset.newBuilder()
+ .setDate(DateUtils.parseDateTime("2007-01-15T00:00:00+0000").getTime())
+ .build())
+ .addChangeset(Changeset.newBuilder()
+ .setDate(DateUtils.parseDateTime("2011-01-01T00:00:00+0000").getTime())
+ .build())
+ .addChangesetIndexByLine(0)
+ .addChangesetIndexByLine(0)
+ .addChangesetIndexByLine(0)
+ .addChangesetIndexByLine(0)
+ .addChangesetIndexByLine(0)
+ .addChangesetIndexByLine(0)
+ .addChangesetIndexByLine(0)
+ .addChangesetIndexByLine(0)
+ .addChangesetIndexByLine(0)
+ .addChangesetIndexByLine(1)
+ .addChangesetIndexByLine(2)
+ .build());
- NewCoverageFileAnalyzer decorator = newDecorator();
decorator.doDecorate(context);
// line 11 has been updated after date1 (2009-12-25). This line is covered.
@@ -92,17 +149,35 @@ public class NewCoverageFileAnalyzerTest {
@Test
public void shouldGetNewConditions() throws ParseException {
- DecoratorContext context = mock(DecoratorContext.class);
when(context.getMeasure(CoreMetrics.COVERAGE_LINE_HITS_DATA)).thenReturn(
new Measure(CoreMetrics.COVERAGE_LINE_HITS_DATA, "10=2;11=3"));
when(context.getMeasure(CoreMetrics.CONDITIONS_BY_LINE)).thenReturn(
new Measure(CoreMetrics.CONDITIONS_BY_LINE, "11=4"));
when(context.getMeasure(CoreMetrics.COVERED_CONDITIONS_BY_LINE)).thenReturn(
new Measure(CoreMetrics.COVERED_CONDITIONS_BY_LINE, "11=1"));
- when(context.getMeasure(CoreMetrics.SCM_LAST_COMMIT_DATETIMES_BY_LINE)).thenReturn(
- new Measure(CoreMetrics.SCM_LAST_COMMIT_DATETIMES_BY_LINE, "10=2007-01-15T00:00:00+0000;11=2011-01-01T00:00:00+0000"));
+ writer.writeComponentScm(Scm.newBuilder()
+ .setComponentRef(1)
+ .addChangeset(Changeset.newBuilder()
+ .build())
+ .addChangeset(Changeset.newBuilder()
+ .setDate(DateUtils.parseDateTime("2007-01-15T00:00:00+0000").getTime())
+ .build())
+ .addChangeset(Changeset.newBuilder()
+ .setDate(DateUtils.parseDateTime("2011-01-01T00:00:00+0000").getTime())
+ .build())
+ .addChangesetIndexByLine(0)
+ .addChangesetIndexByLine(0)
+ .addChangesetIndexByLine(0)
+ .addChangesetIndexByLine(0)
+ .addChangesetIndexByLine(0)
+ .addChangesetIndexByLine(0)
+ .addChangesetIndexByLine(0)
+ .addChangesetIndexByLine(0)
+ .addChangesetIndexByLine(0)
+ .addChangesetIndexByLine(1)
+ .addChangesetIndexByLine(2)
+ .build());
- NewCoverageFileAnalyzer decorator = newDecorator();
decorator.doDecorate(context);
// line 11 has been updated after date1 (2009-12-25). This line has 1 covered condition amongst 4
@@ -124,17 +199,35 @@ public class NewCoverageFileAnalyzerTest {
@Test
public void shouldNotGetNewConditionsWhenNewLineHasNoConditions() throws ParseException {
- DecoratorContext context = mock(DecoratorContext.class);
when(context.getMeasure(CoreMetrics.COVERAGE_LINE_HITS_DATA)).thenReturn(
new Measure(CoreMetrics.COVERAGE_LINE_HITS_DATA, "10=2;11=3"));
when(context.getMeasure(CoreMetrics.CONDITIONS_BY_LINE)).thenReturn(
new Measure(CoreMetrics.CONDITIONS_BY_LINE, "10=1"));
when(context.getMeasure(CoreMetrics.COVERED_CONDITIONS_BY_LINE)).thenReturn(
new Measure(CoreMetrics.COVERED_CONDITIONS_BY_LINE, "10=1"));
- when(context.getMeasure(CoreMetrics.SCM_LAST_COMMIT_DATETIMES_BY_LINE)).thenReturn(
- new Measure(CoreMetrics.SCM_LAST_COMMIT_DATETIMES_BY_LINE, "10=2007-01-15T00:00:00+0000;11=2011-01-01T00:00:00+0000"));
+ writer.writeComponentScm(Scm.newBuilder()
+ .setComponentRef(1)
+ .addChangeset(Changeset.newBuilder()
+ .build())
+ .addChangeset(Changeset.newBuilder()
+ .setDate(DateUtils.parseDateTime("2007-01-15T00:00:00+0000").getTime())
+ .build())
+ .addChangeset(Changeset.newBuilder()
+ .setDate(DateUtils.parseDateTime("2011-01-01T00:00:00+0000").getTime())
+ .build())
+ .addChangesetIndexByLine(0)
+ .addChangesetIndexByLine(0)
+ .addChangesetIndexByLine(0)
+ .addChangesetIndexByLine(0)
+ .addChangesetIndexByLine(0)
+ .addChangesetIndexByLine(0)
+ .addChangesetIndexByLine(0)
+ .addChangesetIndexByLine(0)
+ .addChangesetIndexByLine(0)
+ .addChangesetIndexByLine(1)
+ .addChangesetIndexByLine(2)
+ .build());
- NewCoverageFileAnalyzer decorator = newDecorator();
decorator.doDecorate(context);
// line 11 has been updated after date1 (2009-12-25) but it has no conditions
@@ -144,22 +237,24 @@ public class NewCoverageFileAnalyzerTest {
@Test
public void shouldLeaveNullValueWhenNothingHasChanged() throws Exception {
- String lastCommitDatesByLine = "1=2008-08-02T13:56:37+0200;" +
- "2=2008-08-02T13:56:37+0200;" +
- "3=2008-08-02T13:56:37+0200;" +
- "4=2008-08-02T13:56:37+0200";
- DecoratorContext context = mock(DecoratorContext.class);
when(context.getMeasure(CoreMetrics.COVERAGE_LINE_HITS_DATA)).thenReturn(
new Measure(CoreMetrics.COVERAGE_LINE_HITS_DATA, "2=1;3=1"));
when(context.getMeasure(CoreMetrics.CONDITIONS_BY_LINE)).thenReturn(
new Measure(CoreMetrics.CONDITIONS_BY_LINE, "2=1"));
when(context.getMeasure(CoreMetrics.COVERED_CONDITIONS_BY_LINE)).thenReturn(
new Measure(CoreMetrics.COVERED_CONDITIONS_BY_LINE, "2=1"));
- when(context.getMeasure(CoreMetrics.SCM_LAST_COMMIT_DATETIMES_BY_LINE)).thenReturn(
- new Measure(CoreMetrics.SCM_LAST_COMMIT_DATETIMES_BY_LINE, lastCommitDatesByLine));
+ writer.writeComponentScm(Scm.newBuilder()
+ .setComponentRef(1)
+ .addChangeset(Changeset.newBuilder()
+ .setDate(DateUtils.parseDateTime("2008-08-02T13:56:37+0200").getTime())
+ .build())
+ .addChangesetIndexByLine(0)
+ .addChangesetIndexByLine(0)
+ .addChangesetIndexByLine(0)
+ .addChangesetIndexByLine(0)
+ .build());
- NewCoverageFileAnalyzer decorator = newDecorator();
decorator.doDecorate(context);
verify(context).saveMeasure(argThat(new VariationMatcher(CoreMetrics.NEW_LINES_TO_COVER, 1, null)));
@@ -197,13 +292,6 @@ public class NewCoverageFileAnalyzerTest {
}
}
- private NewCoverageFileAnalyzer newDecorator() throws ParseException {
- List<AbstractNewCoverageFileAnalyzer.PeriodStruct> structs = Arrays.asList(
- new AbstractNewCoverageFileAnalyzer.PeriodStruct(1, newDate("2009-12-25")),
- new AbstractNewCoverageFileAnalyzer.PeriodStruct(3, newDate("2011-02-18")));
- return new NewCoverageFileAnalyzer(structs);
- }
-
private Date newDate(String s) throws ParseException {
return new SimpleDateFormat(DateUtils.DATE_FORMAT).parse(s);
}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/batch/ProjectRepositoryLoader.java b/server/sonar-server/src/main/java/org/sonar/server/batch/ProjectRepositoryLoader.java
index 0ebebdac72a..baac3ce42b2 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/batch/ProjectRepositoryLoader.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/batch/ProjectRepositoryLoader.java
@@ -289,7 +289,8 @@ public class ProjectRepositoryLoader implements ServerComponent {
}
for (FilePathWithHashDto file : dbClient.componentDao().selectEnabledDescendantFiles(session, moduleKey)) {
- FileData fileData = new FileData(file.getSrcHash(), false, null, null, null);
+ // TODO should query E/S to know if blame is missing on this file
+ FileData fileData = new FileData(file.getSrcHash(), true);
ref.addFileData(moduleKeysByUuid.get(file.getModuleUuid()), file.getPath(), fileData);
}
}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/issue/SourceLinesCache.java b/server/sonar-server/src/main/java/org/sonar/server/computation/issue/SourceLinesCache.java
index daec5fb60e4..b49e8abf5f4 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/computation/issue/SourceLinesCache.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/computation/issue/SourceLinesCache.java
@@ -21,6 +21,8 @@ package org.sonar.server.computation.issue;
import org.apache.commons.lang.StringUtils;
import org.sonar.batch.protocol.output.BatchReport;
+import org.sonar.batch.protocol.output.BatchReport.Scm.Changeset;
+import org.sonar.batch.protocol.output.BatchReport.Scm.Changeset.Builder;
import org.sonar.batch.protocol.output.BatchReportReader;
import org.sonar.server.source.index.SourceLineDoc;
import org.sonar.server.source.index.SourceLineIndex;
@@ -28,6 +30,7 @@ import org.sonar.server.source.index.SourceLineIndex;
import javax.annotation.CheckForNull;
import javax.annotation.Nullable;
+import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -120,17 +123,29 @@ public class SourceLinesCache {
BatchReport.Scm.Builder scmBuilder = BatchReport.Scm.newBuilder()
.setComponentRef(currentFileReportRef);
for (SourceLineDoc sourceLine : lines) {
- if (changesetByRevision.get(sourceLine.scmRevision()) == null) {
- BatchReport.Scm.Changeset changeset = BatchReport.Scm.Changeset.newBuilder()
- .setAuthor(sourceLine.scmAuthor())
- .setDate(sourceLine.scmDate().getTime())
- .setRevision(sourceLine.scmRevision())
- .build();
+ String scmRevision = sourceLine.scmRevision();
+ if (scmRevision == null || changesetByRevision.get(scmRevision) == null) {
+ Builder changeSetBuilder = BatchReport.Scm.Changeset.newBuilder();
+ String scmAuthor = sourceLine.scmAuthor();
+ if (scmAuthor != null) {
+ changeSetBuilder.setAuthor(scmAuthor);
+ }
+ Date scmDate = sourceLine.scmDate();
+ if (scmDate != null) {
+ changeSetBuilder.setDate(scmDate.getTime());
+ }
+ if (scmRevision != null) {
+ changeSetBuilder.setRevision(scmRevision);
+ }
+
+ Changeset changeset = changeSetBuilder.build();
scmBuilder.addChangeset(changeset);
scmBuilder.addChangesetIndexByLine(scmBuilder.getChangesetCount() - 1);
- changesetByRevision.put(sourceLine.scmRevision(), changeset);
+ if (scmRevision != null) {
+ changesetByRevision.put(scmRevision, changeset);
+ }
} else {
- scmBuilder.addChangesetIndexByLine(scmBuilder.getChangesetList().indexOf(changesetByRevision.get(sourceLine.scmRevision())));
+ scmBuilder.addChangesetIndexByLine(scmBuilder.getChangesetList().indexOf(changesetByRevision.get(scmRevision)));
}
}
return scmBuilder.build();
diff --git a/server/sonar-server/src/main/java/org/sonar/server/platform/ServerComponents.java b/server/sonar-server/src/main/java/org/sonar/server/platform/ServerComponents.java
index 195e297eb8f..b3137965343 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/platform/ServerComponents.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/platform/ServerComponents.java
@@ -599,10 +599,8 @@ class ServerComponents {
pico.addSingleton(ShowAction.class);
pico.addSingleton(LinesAction.class);
pico.addSingleton(HashAction.class);
- pico.addSingleton(ScmWriter.class);
pico.addSingleton(RawAction.class);
pico.addSingleton(IndexAction.class);
- pico.addSingleton(ScmAction.class);
pico.addSingleton(SourceLineIndexDefinition.class);
pico.addSingleton(SourceLineIndex.class);
pico.addSingleton(SourceLineIndexer.class);
diff --git a/server/sonar-server/src/main/java/org/sonar/server/source/SourceService.java b/server/sonar-server/src/main/java/org/sonar/server/source/SourceService.java
index ed80adb8f94..581df02b837 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/source/SourceService.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/source/SourceService.java
@@ -23,18 +23,12 @@ package org.sonar.server.source;
import org.apache.commons.lang.ObjectUtils;
import org.elasticsearch.common.collect.Lists;
import org.sonar.api.ServerComponent;
-import org.sonar.api.measures.CoreMetrics;
-import org.sonar.api.web.UserRole;
-import org.sonar.core.measure.db.MeasureDto;
-import org.sonar.core.persistence.DbSession;
-import org.sonar.core.persistence.MyBatis;
import org.sonar.server.db.DbClient;
import org.sonar.server.source.index.SourceLineDoc;
import org.sonar.server.source.index.SourceLineIndex;
-import org.sonar.server.user.UserSession;
-import javax.annotation.CheckForNull;
import javax.annotation.Nullable;
+
import java.util.List;
public class SourceService implements ServerComponent {
@@ -74,34 +68,4 @@ public class SourceService implements ServerComponent {
}
return lines;
}
-
- @CheckForNull
- public String getScmAuthorData(String fileKey) {
- checkPermission(fileKey);
- return findDataFromComponent(fileKey, CoreMetrics.SCM_AUTHORS_BY_LINE_KEY);
- }
-
- @CheckForNull
- public String getScmDateData(String fileKey) {
- checkPermission(fileKey);
- return findDataFromComponent(fileKey, CoreMetrics.SCM_LAST_COMMIT_DATETIMES_BY_LINE_KEY);
- }
-
- private void checkPermission(String fileKey) {
- UserSession.get().checkComponentPermission(UserRole.CODEVIEWER, fileKey);
- }
-
- @CheckForNull
- private String findDataFromComponent(String fileKey, String metricKey) {
- DbSession session = dbClient.openSession(false);
- try {
- MeasureDto data = dbClient.measureDao().findByComponentKeyAndMetricKey(session, fileKey, metricKey);
- if (data != null) {
- return data.getData();
- }
- return null;
- } finally {
- MyBatis.closeQuietly(session);
- }
- }
}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/source/ws/ScmAction.java b/server/sonar-server/src/main/java/org/sonar/server/source/ws/ScmAction.java
deleted file mode 100644
index f214b680a10..00000000000
--- a/server/sonar-server/src/main/java/org/sonar/server/source/ws/ScmAction.java
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- * 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.source.ws;
-
-import com.google.common.io.Resources;
-import org.apache.commons.lang.ObjectUtils;
-import org.sonar.api.server.ws.Request;
-import org.sonar.api.server.ws.RequestHandler;
-import org.sonar.api.server.ws.Response;
-import org.sonar.api.server.ws.WebService;
-import org.sonar.api.utils.text.JsonWriter;
-import org.sonar.server.source.SourceService;
-
-public class ScmAction implements RequestHandler {
-
- private final SourceService service;
- private final ScmWriter scmWriter;
-
- public ScmAction(SourceService service, ScmWriter scmWriter) {
- this.service = service;
- this.scmWriter = scmWriter;
- }
-
- void define(WebService.NewController controller) {
- WebService.NewAction action = controller.createAction("scm")
- .setDescription("Get SCM information of source files. Require See Source Code permission on file's project<br/>" +
- "Each element of the result array is composed of:" +
- "<ol>" +
- "<li>Line number</li>" +
- "<li>Author of the commit</li>" +
- "<li>Date of the commit</li>" +
- "</ol>")
- .setSince("4.4")
- .setResponseExample(Resources.getResource(getClass(), "example-scm.json"))
- .setHandler(this);
-
- action
- .createParam("key")
- .setRequired(true)
- .setDescription("File key")
- .setExampleValue("my_project:/src/foo/Bar.php");
-
- action
- .createParam("from")
- .setDescription("First line to return. Starts at 1")
- .setExampleValue("10")
- .setDefaultValue("1");
-
- action
- .createParam("to")
- .setDescription("Last line to return (inclusive)")
- .setExampleValue("20");
-
- action
- .createParam("commits_by_line")
- .setDescription("Group lines by SCM commit if value is false, else display commits for each line, even if two " +
- "consecutive lines relate to the same commit.")
- .setBooleanPossibleValues()
- .setDefaultValue("false");
- }
-
- @Override
- public void handle(Request request, Response response) {
- String fileKey = request.mandatoryParam("key");
-
- String authors = service.getScmAuthorData(fileKey);
- String dates = service.getScmDateData(fileKey);
-
- JsonWriter json = response.newJsonWriter().beginObject();
- int from = Math.max(request.mandatoryParamAsInt("from"), 1);
- int to = (Integer) ObjectUtils.defaultIfNull(request.paramAsInt("to"), Integer.MAX_VALUE);
- scmWriter.write(authors, dates, from, to, request.mandatoryParamAsBoolean("commits_by_line"), json);
- json.endObject().close();
- }
-}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/source/ws/ScmWriter.java b/server/sonar-server/src/main/java/org/sonar/server/source/ws/ScmWriter.java
deleted file mode 100644
index b95300fea51..00000000000
--- a/server/sonar-server/src/main/java/org/sonar/server/source/ws/ScmWriter.java
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * 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.source.ws;
-
-import org.sonar.api.ServerComponent;
-import org.sonar.api.utils.DateUtils;
-import org.sonar.api.utils.KeyValueFormat;
-import org.sonar.api.utils.text.JsonWriter;
-
-import javax.annotation.Nullable;
-
-import java.util.Map;
-
-public class ScmWriter implements ServerComponent {
-
- public void write(@Nullable String authorsData, @Nullable String datesData, int from, int to, boolean showCommitsByLine, JsonWriter json) {
- json.name("scm").beginArray();
- if (authorsData != null) {
- Map<Integer, String> authors = KeyValueFormat.parseIntString(authorsData);
- Map<Integer, String> dates = KeyValueFormat.parseIntString(datesData);
-
- String previousAuthor = null;
- String previousDate = null;
- boolean started = false;
- for (Map.Entry<Integer, String> entry : authors.entrySet()) {
- Integer line = entry.getKey();
- String author = entry.getValue();
- String date = dates.get(line);
- String formattedDate = DateUtils.formatDate(DateUtils.parseDateTime(date));
- if (line >= from && line <= to) {
- if (!started || showCommitsByLine || !isSameCommit(date, previousDate, author, previousAuthor)) {
- json.beginArray();
- json.value(line);
- json.value(author);
- json.value(formattedDate);
- json.endArray();
- started = true;
- }
- }
- previousAuthor = author;
- previousDate = date;
- }
- }
- json.endArray();
- }
-
- private boolean isSameCommit(String date, String previousDate, String author, String previousAuthor) {
- return author.equals(previousAuthor) && date.equals(previousDate);
- }
-}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/source/ws/SourcesWs.java b/server/sonar-server/src/main/java/org/sonar/server/source/ws/SourcesWs.java
index f7dc54420fb..f87834b8714 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/source/ws/SourcesWs.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/source/ws/SourcesWs.java
@@ -27,15 +27,13 @@ public class SourcesWs implements WebService {
private final ShowAction showAction;
private final LinesAction linesAction;
private final RawAction rawAction;
- private final ScmAction scmAction;
private final HashAction hashAction;
private final IndexAction indexAction;
- public SourcesWs(ShowAction showAction, RawAction rawAction, ScmAction scmAction, LinesAction linesAction, HashAction hashAction, IndexAction indexAction) {
+ public SourcesWs(ShowAction showAction, RawAction rawAction, LinesAction linesAction, HashAction hashAction, IndexAction indexAction) {
this.showAction = showAction;
this.linesAction = linesAction;
this.rawAction = rawAction;
- this.scmAction = scmAction;
this.hashAction = hashAction;
this.indexAction = indexAction;
}
@@ -48,7 +46,6 @@ public class SourcesWs implements WebService {
showAction.define(controller);
linesAction.define(controller);
rawAction.define(controller);
- scmAction.define(controller);
hashAction.define(controller);
indexAction.define(controller);
controller.done();
diff --git a/server/sonar-server/src/test/java/org/sonar/server/source/SourceServiceTest.java b/server/sonar-server/src/test/java/org/sonar/server/source/SourceServiceTest.java
index 468f6cdd89b..100348abe6c 100644
--- a/server/sonar-server/src/test/java/org/sonar/server/source/SourceServiceTest.java
+++ b/server/sonar-server/src/test/java/org/sonar/server/source/SourceServiceTest.java
@@ -25,11 +25,9 @@ import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;
-import org.sonar.api.measures.CoreMetrics;
import org.sonar.api.web.UserRole;
import org.sonar.core.persistence.DbSession;
import org.sonar.server.db.DbClient;
-import org.sonar.server.exceptions.ForbiddenException;
import org.sonar.server.measure.persistence.MeasureDao;
import org.sonar.server.source.index.SourceLineDoc;
import org.sonar.server.source.index.SourceLineIndex;
@@ -39,10 +37,9 @@ import java.util.Arrays;
import java.util.List;
import static org.assertj.core.api.Assertions.assertThat;
-import static org.junit.Assert.fail;
-import static org.mockito.Matchers.anyString;
-import static org.mockito.Matchers.eq;
-import static org.mockito.Mockito.*;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
@RunWith(MockitoJUnitRunner.class)
public class SourceServiceTest {
@@ -93,45 +90,6 @@ public class SourceServiceTest {
}
@Test
- public void get_scm_author_data() throws Exception {
- service.getScmAuthorData(COMPONENT_UUID);
- verify(measureDao).findByComponentKeyAndMetricKey(session, COMPONENT_UUID, CoreMetrics.SCM_AUTHORS_BY_LINE_KEY);
- }
-
- @Test
- public void fail_to_get_scm_author_data_if_no_permission() throws Exception {
- MockUserSession.set().setLogin("johh");
- try {
- service.getScmAuthorData(COMPONENT_UUID);
- fail();
- } catch (Exception e) {
- assertThat(e).isInstanceOf(ForbiddenException.class);
- }
- verifyZeroInteractions(measureDao);
- }
-
- @Test
- public void not_get_scm_author_data_if_no_data() throws Exception {
- MockUserSession.set().addComponentPermission(UserRole.CODEVIEWER, PROJECT_KEY, COMPONENT_UUID);
- when(measureDao.findByComponentKeyAndMetricKey(eq(session), anyString(), anyString())).thenReturn(null);
- assertThat(service.getScmAuthorData(COMPONENT_UUID)).isNull();
- }
-
- @Test
- public void get_scm_date_data() throws Exception {
- MockUserSession.set().addComponentPermission(UserRole.CODEVIEWER, PROJECT_KEY, COMPONENT_UUID);
- service.getScmDateData(COMPONENT_UUID);
- verify(measureDao).findByComponentKeyAndMetricKey(session, COMPONENT_UUID, CoreMetrics.SCM_LAST_COMMIT_DATETIMES_BY_LINE_KEY);
- }
-
- @Test
- public void not_get_scm_date_data_if_no_data() throws Exception {
- MockUserSession.set().addComponentPermission(UserRole.CODEVIEWER, PROJECT_KEY, COMPONENT_UUID);
- when(measureDao.findByComponentKeyAndMetricKey(eq(session), anyString(), anyString())).thenReturn(null);
- assertThat(service.getScmDateData(COMPONENT_UUID)).isNull();
- }
-
- @Test
public void getLinesAsTxt() throws Exception {
MockUserSession.set().addComponentPermission(UserRole.CODEVIEWER, PROJECT_KEY, COMPONENT_UUID);
when(sourceLineIndex.getLines(COMPONENT_UUID, 1, Integer.MAX_VALUE)).thenReturn(
diff --git a/server/sonar-server/src/test/java/org/sonar/server/source/ws/HashActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/source/ws/HashActionTest.java
index 65616c6f3c7..5d74342ae99 100644
--- a/server/sonar-server/src/test/java/org/sonar/server/source/ws/HashActionTest.java
+++ b/server/sonar-server/src/test/java/org/sonar/server/source/ws/HashActionTest.java
@@ -67,7 +67,6 @@ public class HashActionTest {
new SourcesWs(
mock(ShowAction.class),
mock(RawAction.class),
- mock(ScmAction.class),
mock(LinesAction.class),
new HashAction(dbClient),
mock(IndexAction.class)
diff --git a/server/sonar-server/src/test/java/org/sonar/server/source/ws/IndexActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/source/ws/IndexActionTest.java
index 079666645dd..efcb5258229 100644
--- a/server/sonar-server/src/test/java/org/sonar/server/source/ws/IndexActionTest.java
+++ b/server/sonar-server/src/test/java/org/sonar/server/source/ws/IndexActionTest.java
@@ -66,7 +66,7 @@ public class IndexActionTest {
public void setUp() throws Exception {
when(dbClient.componentDao()).thenReturn(componentDao);
when(dbClient.openSession(false)).thenReturn(session);
- tester = new WsTester(new SourcesWs(mock(ShowAction.class), mock(RawAction.class), mock(ScmAction.class), mock(LinesAction.class),
+ tester = new WsTester(new SourcesWs(mock(ShowAction.class), mock(RawAction.class), mock(LinesAction.class),
mock(HashAction.class), new IndexAction(dbClient, sourceService)));
}
@@ -116,7 +116,7 @@ public class IndexActionTest {
WsTester.TestRequest request = tester.newGetRequest("api/sources", "index").setParam("resource", fileKey);
try {
request.execute();
- } catch(NotFoundException nfe) {
+ } catch (NotFoundException nfe) {
verify(session).close();
}
}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/source/ws/LinesActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/source/ws/LinesActionTest.java
index bcd67c877c1..91e73188d66 100644
--- a/server/sonar-server/src/test/java/org/sonar/server/source/ws/LinesActionTest.java
+++ b/server/sonar-server/src/test/java/org/sonar/server/source/ws/LinesActionTest.java
@@ -72,18 +72,17 @@ public class LinesActionTest {
new SourcesWs(
mock(ShowAction.class),
mock(RawAction.class),
- mock(ScmAction.class),
new LinesAction(sourceLineIndex, htmlSourceDecorator, componentService),
mock(HashAction.class),
mock(IndexAction.class)
)
- );
+ );
when(htmlSourceDecorator.getDecoratedSourceAsHtml(anyString(), anyString(), anyString())).thenAnswer(new Answer<String>() {
@Override
public String answer(InvocationOnMock invocation) throws Throwable {
return "<span class=\"" + invocation.getArguments()[1] + " sym-" + invocation.getArguments()[2] + "\">" +
StringEscapeUtils.escapeHtml((String) invocation.getArguments()[0]) +
- "</span>";
+ "</span>";
}
});
}
@@ -155,7 +154,7 @@ public class LinesActionTest {
line1,
line2,
line3
- ));
+ ));
String componentKey = "componentKey";
when(componentService.getByUuid(componentUuid)).thenReturn(new ComponentDto().setKey(componentKey).setProjectUuid(projectUuid));
@@ -213,7 +212,7 @@ public class LinesActionTest {
.setItCoveredConditions(null)
.setDuplications(null)
.setUpdateDate(new Date())
- ));
+ ));
WsTester.TestRequest request = tester
.newGetRequest("api/sources", "lines")
.setParam("uuid", fileUuid)
diff --git a/server/sonar-server/src/test/java/org/sonar/server/source/ws/RawActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/source/ws/RawActionTest.java
index ed2f15ef01e..28de2fb6f67 100644
--- a/server/sonar-server/src/test/java/org/sonar/server/source/ws/RawActionTest.java
+++ b/server/sonar-server/src/test/java/org/sonar/server/source/ws/RawActionTest.java
@@ -65,7 +65,7 @@ public class RawActionTest {
public void setUp() throws Exception {
when(dbClient.componentDao()).thenReturn(componentDao);
when(dbClient.openSession(false)).thenReturn(session);
- tester = new WsTester(new SourcesWs(mock(ShowAction.class), new RawAction(dbClient, sourceService), mock(ScmAction.class), mock(LinesAction.class),
+ tester = new WsTester(new SourcesWs(mock(ShowAction.class), new RawAction(dbClient, sourceService), mock(LinesAction.class),
mock(HashAction.class), mock(IndexAction.class)));
}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/source/ws/ScmActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/source/ws/ScmActionTest.java
deleted file mode 100644
index 97ccb21efa6..00000000000
--- a/server/sonar-server/src/test/java/org/sonar/server/source/ws/ScmActionTest.java
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * 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.source.ws;
-
-import org.junit.Test;
-import org.sonar.api.utils.text.JsonWriter;
-import org.sonar.server.source.SourceService;
-import org.sonar.server.ws.WsTester;
-
-import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.eq;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-public class ScmActionTest {
-
- SourceService sourceService = mock(SourceService.class);
- ScmWriter scmWriter = mock(ScmWriter.class);
- WsTester tester = new WsTester(new SourcesWs(mock(ShowAction.class), mock(RawAction.class), new ScmAction(sourceService, scmWriter), mock(LinesAction.class),
- mock(HashAction.class), mock(IndexAction.class)));
-
- @Test
- public void get_scm() throws Exception {
- String fileKey = "src/Foo.java";
- when(sourceService.getScmAuthorData(fileKey)).thenReturn("1=julien");
- when(sourceService.getScmDateData(fileKey)).thenReturn("1=2013-01-01");
-
- WsTester.TestRequest request = tester.newGetRequest("api/sources", "scm").setParam("key", fileKey);
- request.execute();
- verify(scmWriter).write(eq("1=julien"), eq("1=2013-01-01"), eq(1), eq(Integer.MAX_VALUE), eq(false), any(JsonWriter.class));
- }
-
- @Test
- public void do_not_group_lines_by_commit() throws Exception {
- String fileKey = "src/Foo.java";
- when(sourceService.getScmAuthorData(fileKey)).thenReturn("1=julien");
- when(sourceService.getScmDateData(fileKey)).thenReturn("1=2013-01-01");
-
- WsTester.TestRequest request = tester.newGetRequest("api/sources", "scm").setParam("key", fileKey).setParam("commits_by_line", "true");
- request.execute();
- verify(scmWriter).write(eq("1=julien"), eq("1=2013-01-01"), eq(1), eq(Integer.MAX_VALUE), eq(true), any(JsonWriter.class));
- }
-
- @Test
- public void range_of_lines() throws Exception {
- String fileKey = "src/Foo.java";
- when(sourceService.getScmAuthorData(fileKey)).thenReturn("1=julien");
- when(sourceService.getScmDateData(fileKey)).thenReturn("1=2013-01-01");
-
- WsTester.TestRequest request = tester.newGetRequest("api/sources", "scm").setParam("key", fileKey).setParam("from", "3").setParam("to", "20");
- request.execute();
- verify(scmWriter).write(eq("1=julien"), eq("1=2013-01-01"), eq(3), eq(20), eq(false), any(JsonWriter.class));
- }
-
- @Test
- public void accept_negative_from_line() throws Exception {
- String fileKey = "src/Foo.java";
- when(sourceService.getScmAuthorData(fileKey)).thenReturn("1=julien");
- when(sourceService.getScmDateData(fileKey)).thenReturn("1=2013-01-01");
-
- WsTester.TestRequest request = tester.newGetRequest("api/sources", "scm").setParam("key", fileKey).setParam("from", "-3").setParam("to", "20");
- request.execute();
- verify(scmWriter).write(eq("1=julien"), eq("1=2013-01-01"), eq(1), eq(20), eq(false), any(JsonWriter.class));
- }
-}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/source/ws/ScmWriterTest.java b/server/sonar-server/src/test/java/org/sonar/server/source/ws/ScmWriterTest.java
deleted file mode 100644
index cf05251cf34..00000000000
--- a/server/sonar-server/src/test/java/org/sonar/server/source/ws/ScmWriterTest.java
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * 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.source.ws;
-
-import org.junit.Test;
-import org.sonar.api.utils.text.JsonWriter;
-import org.sonar.test.JsonAssert;
-
-import java.io.StringWriter;
-
-public class ScmWriterTest {
-
- ScmWriter writer = new ScmWriter();
-
- @Test
- public void write_authors_and_dates() throws Exception {
- // same commit on lines 1 and 2
- test("1=julien;2=julien;3=simon;", "1=2013-03-13T16:22:31+0100;2=2013-03-13T16:22:31+0100;3=2014-01-01T16:22:31+0100;", 1, Integer.MAX_VALUE, true,
- "{\"scm\": [[1, \"julien\", \"2013-03-13\"], [2, \"julien\", \"2013-03-13\"], [3, \"simon\", \"2014-01-01\"]]}");
- }
-
- @Test
- public void filter_by_range_of_lines() throws Exception {
- String authors = "1=julien;2=simon;";
- String dates = "1=2013-03-13T16:22:31+0100;2=2014-01-01T16:22:31+0100;";
-
- test(authors, dates, 2, 200, true, "{\"scm\": [[2, \"simon\", \"2014-01-01\"]]}");
- test(authors, dates, 3, 5, true, "{\"scm\": []}");
- test(authors, dates, -2, 1, true, "{\"scm\": [[1, \"julien\", \"2013-03-13\"]]}");
- }
-
- @Test
- public void group_by_commits() throws Exception {
- // lines 1 and 2 are the same commit, but not 3 (different date)
- String authors = "1=julien;2=julien;3=julien;4=simon;";
- String dates = "1=2013-03-13T16:22:31+0100;2=2013-03-13T16:22:31+0100;3=2013-03-14T16:22:31+0100;4=2014-01-01T16:22:31+0100";
-
- test(authors, dates, 1, Integer.MAX_VALUE, false,
- "{\"scm\": [[1, \"julien\", \"2013-03-13\"], [3, \"julien\", \"2013-03-14\"], [4, \"simon\", \"2014-01-01\"]]}");
-
- test(authors, dates, 2, 4, false,
- "{\"scm\": [[2, \"julien\", \"2013-03-13\"], [3, \"julien\", \"2013-03-14\"], [4, \"simon\", \"2014-01-01\"]]}");
-
- test(authors, dates, 1, 2, false, "{\"scm\": [[1, \"julien\", \"2013-03-13\"]]}");
- test(authors, dates, 10, 20, false, "{\"scm\": []}");
- }
-
- private void test(String authors, String dates, int from, int to, boolean group, String expected) {
- StringWriter output = new StringWriter();
- JsonWriter jsonWriter = JsonWriter.of(output);
- jsonWriter.beginObject();
- writer.write(authors, dates, from, to, group, jsonWriter);
- jsonWriter.endObject();
- JsonAssert.assertJson(output.toString()).isSimilarTo(expected);
- }
-}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/source/ws/ShowActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/source/ws/ShowActionTest.java
index c3471efa0bb..4763f2f91f6 100644
--- a/server/sonar-server/src/test/java/org/sonar/server/source/ws/ShowActionTest.java
+++ b/server/sonar-server/src/test/java/org/sonar/server/source/ws/ShowActionTest.java
@@ -65,7 +65,7 @@ public class ShowActionTest {
public void setUp() throws Exception {
when(dbClient.componentDao()).thenReturn(componentDao);
when(dbClient.openSession(false)).thenReturn(session);
- tester = new WsTester(new SourcesWs(new ShowAction(sourceService, dbClient), mock(RawAction.class), new ScmAction(sourceService, mock(ScmWriter.class)),
+ tester = new WsTester(new SourcesWs(new ShowAction(sourceService, dbClient), mock(RawAction.class),
mock(LinesAction.class),
mock(HashAction.class),
mock(IndexAction.class)));
diff --git a/server/sonar-server/src/test/java/org/sonar/server/source/ws/SourcesWsTest.java b/server/sonar-server/src/test/java/org/sonar/server/source/ws/SourcesWsTest.java
index f56d738f99e..491d42912e6 100644
--- a/server/sonar-server/src/test/java/org/sonar/server/source/ws/SourcesWsTest.java
+++ b/server/sonar-server/src/test/java/org/sonar/server/source/ws/SourcesWsTest.java
@@ -36,11 +36,10 @@ public class SourcesWsTest {
ShowAction showAction = new ShowAction(mock(SourceService.class), mock(DbClient.class));
RawAction rawAction = new RawAction(mock(DbClient.class), mock(SourceService.class));
- ScmAction scmAction = new ScmAction(mock(SourceService.class), new ScmWriter());
LinesAction linesAction = new LinesAction(mock(SourceLineIndex.class), mock(HtmlSourceDecorator.class), mock(ComponentService.class));
HashAction hashAction = new HashAction(mock(DbClient.class));
IndexAction indexAction = new IndexAction(mock(DbClient.class), mock(SourceService.class));
- WsTester tester = new WsTester(new SourcesWs(showAction, rawAction, scmAction, linesAction, hashAction, indexAction));
+ WsTester tester = new WsTester(new SourcesWs(showAction, rawAction, linesAction, hashAction, indexAction));
@Test
public void define_ws() throws Exception {
@@ -48,7 +47,7 @@ public class SourcesWsTest {
assertThat(controller).isNotNull();
assertThat(controller.since()).isEqualTo("4.2");
assertThat(controller.description()).isNotEmpty();
- assertThat(controller.actions()).hasSize(6);
+ assertThat(controller.actions()).hasSize(5);
WebService.Action show = controller.action("show");
assertThat(show).isNotNull();
@@ -66,14 +65,6 @@ public class SourcesWsTest {
assertThat(raw.responseExampleAsString()).isNotEmpty();
assertThat(raw.params()).hasSize(1);
- WebService.Action scm = controller.action("scm");
- assertThat(scm).isNotNull();
- assertThat(scm.handler()).isSameAs(scmAction);
- assertThat(scm.since()).isEqualTo("4.4");
- assertThat(scm.isInternal()).isFalse();
- assertThat(scm.responseExampleAsString()).isNotEmpty();
- assertThat(scm.params()).hasSize(4);
-
WebService.Action lines = controller.action("lines");
assertThat(lines).isNotNull();
assertThat(lines.handler()).isSameAs(linesAction);
diff --git a/sonar-batch-protocol/src/main/java/org/sonar/batch/protocol/input/FileData.java b/sonar-batch-protocol/src/main/java/org/sonar/batch/protocol/input/FileData.java
index d68bcbd3c61..28b8083c0e2 100644
--- a/sonar-batch-protocol/src/main/java/org/sonar/batch/protocol/input/FileData.java
+++ b/sonar-batch-protocol/src/main/java/org/sonar/batch/protocol/input/FileData.java
@@ -26,16 +26,10 @@ public class FileData {
private final String hash;
private final boolean needBlame;
- private final String scmLastCommitDatetimesByLine;
- private final String scmRevisionsByLine;
- private final String scmAuthorsByLine;
- public FileData(@Nullable String hash, boolean needBlame, @Nullable String scmLastCommitDatetimesByLine, @Nullable String scmRevisionsByLine, @Nullable String scmAuthorsByLine) {
+ public FileData(@Nullable String hash, boolean needBlame) {
this.hash = hash;
this.needBlame = needBlame;
- this.scmLastCommitDatetimesByLine = scmLastCommitDatetimesByLine;
- this.scmRevisionsByLine = scmRevisionsByLine;
- this.scmAuthorsByLine = scmAuthorsByLine;
}
@CheckForNull
@@ -47,19 +41,4 @@ public class FileData {
return needBlame;
}
- @CheckForNull
- public String scmLastCommitDatetimesByLine() {
- return scmLastCommitDatetimesByLine;
- }
-
- @CheckForNull
- public String scmRevisionsByLine() {
- return scmRevisionsByLine;
- }
-
- @CheckForNull
- public String scmAuthorsByLine() {
- return scmAuthorsByLine;
- }
-
}
diff --git a/sonar-batch-protocol/src/test/java/org/sonar/batch/protocol/input/ProjectRepositoriesTest.java b/sonar-batch-protocol/src/test/java/org/sonar/batch/protocol/input/ProjectRepositoriesTest.java
index b86b2938f15..91a1b171df6 100644
--- a/sonar-batch-protocol/src/test/java/org/sonar/batch/protocol/input/ProjectRepositoriesTest.java
+++ b/sonar-batch-protocol/src/test/java/org/sonar/batch/protocol/input/ProjectRepositoriesTest.java
@@ -50,8 +50,8 @@ public class ProjectRepositoriesTest {
ref.addActiveRule(activeRule);
ref.setLastAnalysisDate(DATE_FORMAT.parse("2014-05-18T15:50:45+0100"));
ref.setTimestamp(10);
- ref.addFileData("foo", "src/main/java/Foo.java", new FileData("xyz", true, "1=12345,2=3456", "1=345,2=345", "1=henryju,2=gaudin"));
- ref.addFileData("foo", "src/main/java/Foo2.java", new FileData("xyz", false, "1=12345,2=3456", "1=345,2=345", "1=henryju,2=gaudin"));
+ ref.addFileData("foo", "src/main/java/Foo.java", new FileData("xyz", true));
+ ref.addFileData("foo", "src/main/java/Foo2.java", new FileData("xyz", false));
JsonAssert.assertJson(ref.toJson())
.isSimilarTo(getClass().getResource("ProjectRepositoriesTest/testToJson.json"));
@@ -89,9 +89,6 @@ public class ProjectRepositoriesTest {
assertThat(ref.fileData("foo", "src/main/java/Foo.java").hash()).isEqualTo("xyz");
assertThat(ref.fileData("foo", "src/main/java/Foo.java").needBlame()).isTrue();
- assertThat(ref.fileData("foo", "src/main/java/Foo.java").scmAuthorsByLine()).isEqualTo("1=henryju,2=gaudin");
- assertThat(ref.fileData("foo", "src/main/java/Foo.java").scmLastCommitDatetimesByLine()).isEqualTo("1=12345,2=3456");
- assertThat(ref.fileData("foo", "src/main/java/Foo.java").scmRevisionsByLine()).isEqualTo("1=345,2=345");
assertThat(ref.lastAnalysisDate().getTime()).isEqualTo(DATE_FORMAT.parse("2014-10-31T00:00:00+0100").getTime());
}
diff --git a/sonar-batch-protocol/src/test/resources/org/sonar/batch/protocol/input/ProjectRepositoriesTest/testToJson.json b/sonar-batch-protocol/src/test/resources/org/sonar/batch/protocol/input/ProjectRepositoriesTest/testToJson.json
index 7b5e29c3695..d728bdc4414 100644
--- a/sonar-batch-protocol/src/test/resources/org/sonar/batch/protocol/input/ProjectRepositoriesTest/testToJson.json
+++ b/sonar-batch-protocol/src/test/resources/org/sonar/batch/protocol/input/ProjectRepositoriesTest/testToJson.json
@@ -32,16 +32,10 @@
"src/main/java/Foo.java": {
"hash": "xyz",
"needBlame": true,
- "scmLastCommitDatetimesByLine": "1\u003d12345,2\u003d3456",
- "scmRevisionsByLine": "1\u003d345,2\u003d345",
- "scmAuthorsByLine": "1\u003dhenryju,2\u003dgaudin"
},
"src/main/java/Foo2.java": {
"hash": "xyz",
"needBlame": false,
- "scmLastCommitDatetimesByLine": "1\u003d12345,2\u003d3456",
- "scmRevisionsByLine": "1\u003d345,2\u003d345",
- "scmAuthorsByLine": "1\u003dhenryju,2\u003dgaudin"
}
}
},
diff --git a/sonar-batch/src/main/java/org/sonar/batch/index/DefaultIndex.java b/sonar-batch/src/main/java/org/sonar/batch/index/DefaultIndex.java
index ff223b4b9f4..33f6246ea8c 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/index/DefaultIndex.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/index/DefaultIndex.java
@@ -70,11 +70,7 @@ public class DefaultIndex extends SonarIndex {
CoreMetrics.FILE_FEEDBACK_EDGES,
CoreMetrics.FILE_TANGLE_INDEX,
CoreMetrics.FILE_TANGLES,
- // Computed by ScmSensor
- CoreMetrics.SCM_AUTHORS_BY_LINE,
- CoreMetrics.SCM_LAST_COMMIT_DATETIMES_BY_LINE,
- CoreMetrics.SCM_REVISIONS_BY_LINE,
- // Computed by core duplication plugin
+ // Computed by CpdSensor
CoreMetrics.DUPLICATIONS_DATA,
CoreMetrics.DUPLICATION_LINES_DATA,
CoreMetrics.DUPLICATED_FILES,
diff --git a/sonar-batch/src/main/java/org/sonar/batch/index/ResourceCache.java b/sonar-batch/src/main/java/org/sonar/batch/index/ResourceCache.java
index 4a97a6c8ab8..3b1ec2fe187 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/index/ResourceCache.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/index/ResourceCache.java
@@ -23,6 +23,8 @@ import com.google.common.base.Preconditions;
import com.google.common.base.Strings;
import com.google.common.collect.Maps;
import org.sonar.api.BatchComponent;
+import org.sonar.api.batch.fs.InputFile;
+import org.sonar.api.batch.fs.internal.DefaultInputFile;
import org.sonar.api.resources.Library;
import org.sonar.api.resources.Resource;
@@ -54,6 +56,10 @@ public class ResourceCache implements BatchComponent {
}
}
+ public BatchResource get(InputFile inputFile) {
+ return resources.get(((DefaultInputFile) inputFile).key());
+ }
+
public BatchResource add(Resource resource, @Nullable Resource parentResource) {
String componentKey = resource.getEffectiveKey();
Preconditions.checkState(!Strings.isNullOrEmpty(componentKey), "Missing resource effective key");
diff --git a/sonar-batch/src/main/java/org/sonar/batch/index/SourceDataFactory.java b/sonar-batch/src/main/java/org/sonar/batch/index/SourceDataFactory.java
index 2aa0b854e01..d2197170309 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/index/SourceDataFactory.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/index/SourceDataFactory.java
@@ -30,10 +30,13 @@ import org.sonar.api.batch.sensor.highlighting.internal.SyntaxHighlightingRule;
import org.sonar.api.measures.CoreMetrics;
import org.sonar.api.measures.Measure;
import org.sonar.api.source.Symbol;
-import org.sonar.api.utils.DateUtils;
import org.sonar.api.utils.KeyValueFormat;
import org.sonar.batch.duplication.DuplicationCache;
import org.sonar.batch.highlighting.SyntaxHighlightingData;
+import org.sonar.batch.protocol.output.BatchReport.Scm;
+import org.sonar.batch.protocol.output.BatchReport.Scm.Changeset;
+import org.sonar.batch.protocol.output.BatchReportReader;
+import org.sonar.batch.report.PublishReportJob;
import org.sonar.batch.scan.filesystem.InputFileMetadata;
import org.sonar.batch.scan.measure.MeasureCache;
import org.sonar.batch.source.CodeColorizers;
@@ -41,6 +44,7 @@ import org.sonar.batch.symbol.SymbolData;
import org.sonar.core.source.SnapshotDataTypes;
import org.sonar.core.source.db.FileSourceDto;
import org.sonar.server.source.db.FileSourceDb;
+import org.sonar.server.source.db.FileSourceDb.Data.Builder;
import java.io.IOException;
import java.util.*;
@@ -57,18 +61,24 @@ public class SourceDataFactory implements BatchComponent {
private final ComponentDataCache componentDataCache;
private final DuplicationCache duplicationCache;
private final CodeColorizers codeColorizers;
+ private final PublishReportJob publishReportJob;
+
+ private final ResourceCache resourceCache;
public SourceDataFactory(MeasureCache measureCache, ComponentDataCache componentDataCache,
- DuplicationCache duplicationCache, CodeColorizers codeColorizers) {
+ DuplicationCache duplicationCache, CodeColorizers codeColorizers, PublishReportJob publishReportJob, ResourceCache resourceCache) {
this.measureCache = measureCache;
this.componentDataCache = componentDataCache;
this.duplicationCache = duplicationCache;
this.codeColorizers = codeColorizers;
+ this.publishReportJob = publishReportJob;
+ this.resourceCache = resourceCache;
}
public byte[] consolidateData(DefaultInputFile inputFile, InputFileMetadata metadata) throws IOException {
FileSourceDb.Data.Builder dataBuilder = createForSource(inputFile);
applyLineMeasures(inputFile, dataBuilder);
+ applyScm(inputFile, dataBuilder);
applyDuplications(inputFile.key(), dataBuilder);
applyHighlighting(inputFile, metadata, dataBuilder);
applySymbolReferences(inputFile, metadata, dataBuilder);
@@ -90,25 +100,30 @@ public class SourceDataFactory implements BatchComponent {
return result;
}
- void applyLineMeasures(DefaultInputFile file, FileSourceDb.Data.Builder dataBuilder) {
- applyLineMeasure(file.key(), CoreMetrics.SCM_AUTHORS_BY_LINE_KEY, dataBuilder, new MeasureOperation() {
- @Override
- public void apply(String value, FileSourceDb.Line.Builder lineBuilder) {
- lineBuilder.setScmAuthor(value);
- }
- });
- applyLineMeasure(file.key(), CoreMetrics.SCM_REVISIONS_BY_LINE_KEY, dataBuilder, new MeasureOperation() {
- @Override
- public void apply(String value, FileSourceDb.Line.Builder lineBuilder) {
- lineBuilder.setScmRevision(value);
- }
- });
- applyLineMeasure(file.key(), CoreMetrics.SCM_LAST_COMMIT_DATETIMES_BY_LINE_KEY, dataBuilder, new MeasureOperation() {
- @Override
- public void apply(String value, FileSourceDb.Line.Builder lineBuilder) {
- lineBuilder.setScmDate(DateUtils.parseDateTimeQuietly(value).getTime());
+ void applyScm(DefaultInputFile inputFile, Builder dataBuilder) {
+ BatchReportReader reader = new BatchReportReader(publishReportJob.getReportDir());
+ Scm componentScm = reader.readComponentScm(resourceCache.get(inputFile).batchId());
+ if (componentScm != null) {
+ for (int i = 0; i < componentScm.getChangesetIndexByLineCount(); i++) {
+ int index = componentScm.getChangesetIndexByLine(i);
+ Changeset changeset = componentScm.getChangeset(index);
+ if (i < dataBuilder.getLinesCount()) {
+ FileSourceDb.Line.Builder lineBuilder = dataBuilder.getLinesBuilder(i);
+ if (changeset.hasAuthor()) {
+ lineBuilder.setScmAuthor(changeset.getAuthor());
+ }
+ if (changeset.hasRevision()) {
+ lineBuilder.setScmRevision(changeset.getRevision());
+ }
+ if (changeset.hasDate()) {
+ lineBuilder.setScmDate(changeset.getDate());
+ }
+ }
}
- });
+ }
+ }
+
+ void applyLineMeasures(DefaultInputFile file, FileSourceDb.Data.Builder dataBuilder) {
applyLineMeasure(file.key(), CoreMetrics.COVERAGE_LINE_HITS_DATA_KEY, dataBuilder, new MeasureOperation() {
@Override
public void apply(String value, FileSourceDb.Line.Builder lineBuilder) {
@@ -167,17 +182,16 @@ public class SourceDataFactory implements BatchComponent {
void applyLineMeasure(String inputFileKey, String metricKey, FileSourceDb.Data.Builder to, MeasureOperation op) {
Iterable<Measure> measures = measureCache.byMetric(inputFileKey, metricKey);
- if (measures != null) {
- for (Measure measure : measures) {
- Map<Integer, String> lineMeasures = KeyValueFormat.parseIntString((String) measure.value());
- for (Map.Entry<Integer, String> lineMeasure : lineMeasures.entrySet()) {
- int lineIdx = lineMeasure.getKey();
- if (lineIdx <= to.getLinesCount()) {
- String value = lineMeasure.getValue();
- if (StringUtils.isNotEmpty(value)) {
- FileSourceDb.Line.Builder lineBuilder = to.getLinesBuilder(lineIdx - 1);
- op.apply(value, lineBuilder);
- }
+ if (measures.iterator().hasNext()) {
+ Measure measure = measures.iterator().next();
+ Map<Integer, String> lineMeasures = KeyValueFormat.parseIntString((String) measure.value());
+ for (Map.Entry<Integer, String> lineMeasure : lineMeasures.entrySet()) {
+ int lineIdx = lineMeasure.getKey();
+ if (lineIdx <= to.getLinesCount()) {
+ String value = lineMeasure.getValue();
+ if (StringUtils.isNotEmpty(value)) {
+ FileSourceDb.Line.Builder lineBuilder = to.getLinesBuilder(lineIdx - 1);
+ op.apply(value, lineBuilder);
}
}
}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/mediumtest/BatchMediumTester.java b/sonar-batch/src/main/java/org/sonar/batch/mediumtest/BatchMediumTester.java
index ed0142bcace..6200c172993 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/mediumtest/BatchMediumTester.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/mediumtest/BatchMediumTester.java
@@ -36,6 +36,7 @@ import org.sonar.batch.bootstrapper.EnvironmentInformation;
import org.sonar.batch.issue.tracking.ServerLineHashesLoader;
import org.sonar.batch.protocol.input.*;
import org.sonar.batch.protocol.input.BatchInput.ServerIssue;
+import org.sonar.batch.report.PublishReportJob;
import org.sonar.batch.repository.GlobalRepositoriesLoader;
import org.sonar.batch.repository.ProjectRepositoriesLoader;
import org.sonar.batch.repository.ServerIssuesLoader;
@@ -61,6 +62,7 @@ public class BatchMediumTester {
public static BatchMediumTesterBuilder builder() {
BatchMediumTesterBuilder builder = new BatchMediumTesterBuilder().registerCoreMetrics();
builder.bootstrapProperties.put(MEDIUM_TEST_ENABLED, "true");
+ builder.bootstrapProperties.put(PublishReportJob.KEEP_REPORT_PROP_KEY, "true");
builder.bootstrapProperties.put(CoreProperties.WORKING_DIRECTORY, Files.createTempDir().getAbsolutePath());
return builder;
}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/report/PublishReportJob.java b/sonar-batch/src/main/java/org/sonar/batch/report/PublishReportJob.java
index 3a70259bede..9fe5d4bbd8b 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/report/PublishReportJob.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/report/PublishReportJob.java
@@ -22,13 +22,16 @@ package org.sonar.batch.report;
import com.github.kevinsawicki.http.HttpRequest;
import com.google.common.annotations.VisibleForTesting;
import org.apache.commons.io.FileUtils;
+import org.codehaus.plexus.personality.plexus.lifecycle.phase.Startable;
+import org.codehaus.plexus.personality.plexus.lifecycle.phase.StartingException;
+import org.codehaus.plexus.personality.plexus.lifecycle.phase.StoppingException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.sonar.api.BatchComponent;
import org.sonar.api.CoreProperties;
+import org.sonar.api.batch.bootstrap.ProjectReactor;
import org.sonar.api.config.Settings;
import org.sonar.api.platform.Server;
-import org.sonar.api.resources.Project;
import org.sonar.api.utils.TempFolder;
import org.sonar.api.utils.ZipUtils;
import org.sonar.batch.bootstrap.DefaultAnalysisMode;
@@ -40,33 +43,55 @@ import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
-public class PublishReportJob implements BatchComponent {
+public class PublishReportJob implements BatchComponent, Startable {
private static final Logger LOG = LoggerFactory.getLogger(PublishReportJob.class);
+ public static final String KEEP_REPORT_PROP_KEY = "sonar.batch.keepReport";
private final ServerClient serverClient;
private final Server server;
private final Settings settings;
- private final Project project;
+ private final ProjectReactor projectReactor;
private final DefaultAnalysisMode analysisMode;
private final TempFolder temp;
private ReportPublisher[] publishers;
+ private File reportDir;
+ private BatchReportWriter writer;
+
public PublishReportJob(Settings settings, ServerClient serverClient, Server server,
- Project project, DefaultAnalysisMode analysisMode, TempFolder temp, ReportPublisher[] publishers) {
+ ProjectReactor projectReactor, DefaultAnalysisMode analysisMode, TempFolder temp, ReportPublisher[] publishers) {
this.serverClient = serverClient;
this.server = server;
- this.project = project;
+ this.projectReactor = projectReactor;
this.settings = settings;
this.analysisMode = analysisMode;
this.temp = temp;
this.publishers = publishers;
}
- public PublishReportJob(Settings settings, ServerClient serverClient, Server server,
- Project project, DefaultAnalysisMode analysisMode, TempFolder temp) {
- this(settings, serverClient, server, project, analysisMode, temp, new ReportPublisher[0]);
+ @Override
+ public void start() throws StartingException {
+ reportDir = new File(projectReactor.getRoot().getWorkDir(), "batch-report");
+ writer = new BatchReportWriter(reportDir);
+ }
+
+ @Override
+ public void stop() throws StoppingException {
+ if (!settings.getBoolean(KEEP_REPORT_PROP_KEY)) {
+ FileUtils.deleteQuietly(reportDir);
+ } else {
+ LOG.info("Batch report generated in " + reportDir);
+ }
+ }
+
+ public File getReportDir() {
+ return reportDir;
+ }
+
+ public BatchReportWriter getWriter() {
+ return writer;
}
public void execute() {
@@ -83,8 +108,6 @@ public class PublishReportJob implements BatchComponent {
private File prepareReport() {
try {
long startTime = System.currentTimeMillis();
- File reportDir = temp.newDir("batch-report");
- BatchReportWriter writer = new BatchReportWriter(reportDir);
for (ReportPublisher publisher : publishers) {
publisher.publish(writer);
}
@@ -94,7 +117,6 @@ public class PublishReportJob implements BatchComponent {
startTime = System.currentTimeMillis();
File reportZip = temp.newFile("batch-report", ".zip");
ZipUtils.zipDir(reportDir, reportZip);
- FileUtils.deleteDirectory(reportDir);
stopTime = System.currentTimeMillis();
LOG.info("Analysis reports compressed in " + (stopTime - startTime) + "ms, zip size=" + FileUtils.byteCountToDisplaySize(FileUtils.sizeOf(reportZip)));
return reportZip;
@@ -109,7 +131,8 @@ public class PublishReportJob implements BatchComponent {
long startTime = System.currentTimeMillis();
URL url;
try {
- url = new URL(serverClient.getURL() + "/api/computation/submit_report?projectKey=" + project.getEffectiveKey());
+ String effectiveKey = projectReactor.getRoot().getKeyWithBranch();
+ url = new URL(serverClient.getURL() + "/api/computation/submit_report?projectKey=" + effectiveKey);
} catch (MalformedURLException e) {
throw new IllegalArgumentException("Invalid URL", e);
}
@@ -148,7 +171,8 @@ public class PublishReportJob implements BatchComponent {
if (!baseUrl.endsWith("/")) {
baseUrl += "/";
}
- String url = baseUrl + "dashboard/index/" + project.getKey();
+ String effectiveKey = projectReactor.getRoot().getKeyWithBranch();
+ String url = baseUrl + "dashboard/index/" + effectiveKey;
logger.info("ANALYSIS SUCCESSFUL, you can browse {}", url);
logger.info("Note that you will be able to access the updated dashboard once the server has processed the submitted analysis report.");
}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/repository/ProjectScmRepositoryLoader.java b/sonar-batch/src/main/java/org/sonar/batch/repository/ProjectScmRepositoryLoader.java
deleted file mode 100644
index a5ee07dd685..00000000000
--- a/sonar-batch/src/main/java/org/sonar/batch/repository/ProjectScmRepositoryLoader.java
+++ /dev/null
@@ -1,155 +0,0 @@
-/*
- * 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.batch.repository;
-
-import com.google.common.collect.Maps;
-import org.sonar.api.BatchComponent;
-import org.sonar.api.batch.RequiresDB;
-import org.sonar.api.batch.bootstrap.ProjectDefinition;
-import org.sonar.api.batch.bootstrap.ProjectReactor;
-import org.sonar.api.database.DatabaseSession;
-import org.sonar.api.database.model.MeasureModel;
-import org.sonar.api.database.model.ResourceModel;
-import org.sonar.api.database.model.Snapshot;
-import org.sonar.api.measures.CoreMetrics;
-import org.sonar.api.measures.Metric;
-import org.sonar.api.resources.Qualifiers;
-import org.sonar.batch.protocol.input.FileData;
-import org.sonar.batch.protocol.input.ProjectRepositories;
-
-import javax.annotation.CheckForNull;
-import javax.persistence.NoResultException;
-import javax.persistence.Query;
-
-import java.util.Arrays;
-import java.util.Date;
-import java.util.List;
-import java.util.Map;
-import java.util.Map.Entry;
-
-import static org.sonar.api.utils.DateUtils.longToDate;
-
-/**
- * Waiting for SCM measure copy to be handled in computation stack we need to get previous measures from DB
- */
-@RequiresDB
-public class ProjectScmRepositoryLoader implements BatchComponent {
-
- private final DatabaseSession session;
- private final ProjectReactor reactor;
- private final ProjectRepositories ref;
-
- public ProjectScmRepositoryLoader(DatabaseSession session, ProjectReactor reactor, ProjectRepositories ref) {
- this.session = session;
- this.reactor = reactor;
- this.ref = ref;
- }
-
- public void complete() {
- for (ProjectDefinition module : reactor.getProjects()) {
-
- for (Entry<String, FileData> fileDataByPaths : ref.fileDataByPath(module.getKeyWithBranch()).entrySet()) {
- String path = fileDataByPaths.getKey();
- FileData fileData = fileDataByPaths.getValue();
- String lastCommits = null;
- String revisions = null;
- String authors = null;
- List<Object[]> measuresByKey = query(module.getKeyWithBranch() + ":" + path, CoreMetrics.SCM_LAST_COMMIT_DATETIMES_BY_LINE_KEY, CoreMetrics.SCM_REVISIONS_BY_LINE_KEY,
- CoreMetrics.SCM_AUTHORS_BY_LINE_KEY);
- for (Object[] measureByKey : measuresByKey) {
- if (measureByKey[0].equals(CoreMetrics.SCM_LAST_COMMIT_DATETIMES_BY_LINE_KEY)) {
- lastCommits = ((MeasureModel) measureByKey[1]).getData(CoreMetrics.SCM_LAST_COMMIT_DATETIMES_BY_LINE);
- } else if (measureByKey[0].equals(CoreMetrics.SCM_REVISIONS_BY_LINE_KEY)) {
- revisions = ((MeasureModel) measureByKey[1]).getData(CoreMetrics.SCM_REVISIONS_BY_LINE);
- } else if (measureByKey[0].equals(CoreMetrics.SCM_AUTHORS_BY_LINE_KEY)) {
- authors = ((MeasureModel) measureByKey[1]).getData(CoreMetrics.SCM_AUTHORS_BY_LINE);
- }
- }
- ref.addFileData(module.getKeyWithBranch(), path, new FileData(fileData.hash(), authors == null, lastCommits, revisions, authors));
- }
- }
- ref.setLastAnalysisDate(lastSnapshotCreationDate(reactor.getRoot().getKeyWithBranch()));
- }
-
- private List<Object[]> query(String resourceKey, String... metricKeys) {
- StringBuilder sb = new StringBuilder();
- Map<String, Object> params = Maps.newHashMap();
-
- sb.append("SELECT met.key, m");
- sb.append(" FROM ")
- .append(MeasureModel.class.getSimpleName())
- .append(" m, ")
- .append(Metric.class.getSimpleName())
- .append(" met, ")
- .append(ResourceModel.class.getSimpleName())
- .append(" r, ")
- .append(Snapshot.class.getSimpleName())
- .append(" s WHERE met.id=m.metricId AND m.snapshotId=s.id AND s.resourceId=r.id AND r.key=:kee AND s.status=:status AND s.qualifier<>:lib");
- params.put("kee", resourceKey);
- params.put("status", Snapshot.STATUS_PROCESSED);
- params.put("lib", Qualifiers.LIBRARY);
-
- sb.append(" AND m.characteristicId IS NULL");
- sb.append(" AND m.personId IS NULL");
- sb.append(" AND m.ruleId IS NULL AND m.rulePriority IS NULL");
- if (metricKeys.length > 0) {
- sb.append(" AND met.key IN (:metricKeys) ");
- params.put("metricKeys", Arrays.asList(metricKeys));
- }
- sb.append(" AND s.last=true ");
- sb.append(" ORDER BY s.createdAt ");
-
- Query jpaQuery = session.createQuery(sb.toString());
-
- for (Map.Entry<String, Object> entry : params.entrySet()) {
- jpaQuery.setParameter(entry.getKey(), entry.getValue());
- }
- return jpaQuery.getResultList();
- }
-
- @CheckForNull
- Date lastSnapshotCreationDate(String resourceKey) {
- StringBuilder sb = new StringBuilder();
- Map<String, Object> params = Maps.newHashMap();
-
- sb.append("SELECT s.buildDate");
- sb.append(" FROM ")
- .append(ResourceModel.class.getSimpleName())
- .append(" r, ")
- .append(Snapshot.class.getSimpleName())
- .append(" s WHERE s.resourceId=r.id AND r.key=:kee AND s.status=:status AND s.qualifier<>:lib");
- params.put("kee", resourceKey);
- params.put("status", Snapshot.STATUS_PROCESSED);
- params.put("lib", Qualifiers.LIBRARY);
-
- sb.append(" AND s.last=true ");
-
- Query jpaQuery = session.createQuery(sb.toString());
-
- for (Map.Entry<String, Object> entry : params.entrySet()) {
- jpaQuery.setParameter(entry.getKey(), entry.getValue());
- }
- try {
- return longToDate((Long) jpaQuery.getSingleResult());
- } catch (NoResultException e) {
- return null;
- }
- }
-}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/scan/ProjectReactorReady.java b/sonar-batch/src/main/java/org/sonar/batch/scan/ProjectReactorReady.java
index 45b4700e795..85ea965e514 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/scan/ProjectReactorReady.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/scan/ProjectReactorReady.java
@@ -22,7 +22,6 @@ package org.sonar.batch.scan;
import org.sonar.api.batch.bootstrap.ProjectBuilder;
import org.sonar.api.batch.bootstrap.ProjectReactor;
import org.sonar.api.batch.bootstrap.internal.ProjectBuilderContext;
-import org.sonar.batch.repository.ProjectScmRepositoryLoader;
import javax.annotation.Nullable;
@@ -43,27 +42,16 @@ public class ProjectReactorReady {
private final ProjectBuilder[] projectBuilders;
private final ProjectExclusions exclusions;
private final ProjectReactorValidator validator;
- private final ProjectScmRepositoryLoader projectScmRepositoryLoader;
- public ProjectReactorReady(ProjectExclusions exclusions, ProjectReactor reactor, @Nullable ProjectBuilder[] projectBuilders, ProjectReactorValidator validator,
- @Nullable ProjectScmRepositoryLoader projectScmRepositoryLoader) {
+ public ProjectReactorReady(ProjectExclusions exclusions, ProjectReactor reactor, @Nullable ProjectBuilder[] projectBuilders, ProjectReactorValidator validator) {
this.exclusions = exclusions;
this.reactor = reactor;
this.projectBuilders = projectBuilders;
this.validator = validator;
- this.projectScmRepositoryLoader = projectScmRepositoryLoader;
- }
-
- public ProjectReactorReady(ProjectExclusions exclusions, ProjectReactor reactor, @Nullable ProjectBuilder[] projectBuilders, ProjectReactorValidator validator) {
- this(exclusions, reactor, projectBuilders, validator, null);
- }
-
- public ProjectReactorReady(ProjectExclusions exclusions, ProjectReactor reactor, ProjectReactorValidator validator, ProjectScmRepositoryLoader projectScmRepositoryLoader) {
- this(exclusions, reactor, new ProjectBuilder[0], validator, projectScmRepositoryLoader);
}
public ProjectReactorReady(ProjectExclusions exclusions, ProjectReactor reactor, ProjectReactorValidator validator) {
- this(exclusions, reactor, new ProjectBuilder[0], validator, null);
+ this(exclusions, reactor, new ProjectBuilder[0], validator);
}
public void start() {
@@ -80,10 +68,5 @@ public class ProjectReactorReady {
// 3 Validate final reactor
validator.validate(reactor);
- // 4 Complete missing SCM information from project repositories
- if (projectScmRepositoryLoader != null) {
- projectScmRepositoryLoader.complete();
- }
-
}
}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/scan/ProjectScanContainer.java b/sonar-batch/src/main/java/org/sonar/batch/scan/ProjectScanContainer.java
index ffa93f69285..aaa63f0d328 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/scan/ProjectScanContainer.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/scan/ProjectScanContainer.java
@@ -51,9 +51,8 @@ import org.sonar.batch.mediumtest.ScanTaskObservers;
import org.sonar.batch.phases.GraphPersister;
import org.sonar.batch.profiling.PhasesSumUpTimeProfiler;
import org.sonar.batch.qualitygate.QualityGateProvider;
-import org.sonar.batch.report.EventCache;
+import org.sonar.batch.report.*;
import org.sonar.batch.repository.ProjectRepositoriesProvider;
-import org.sonar.batch.repository.ProjectScmRepositoryLoader;
import org.sonar.batch.repository.language.DefaultLanguagesRepository;
import org.sonar.batch.rule.ActiveRulesProvider;
import org.sonar.batch.rule.RulesProvider;
@@ -187,6 +186,12 @@ public class ProjectScanContainer extends ComponentContainer {
ProjectSettings.class,
+ // Report
+ PublishReportJob.class,
+ ComponentsPublisher.class,
+ IssuesPublisher.class,
+ MeasuresPublisher.class,
+
ScanTaskObservers.class);
}
@@ -196,8 +201,6 @@ public class ProjectScanContainer extends ComponentContainer {
SourcePersister.class,
ResourceKeyMigration.class,
- ProjectScmRepositoryLoader.class,
-
// Users
DefaultUserFinder.class,
diff --git a/sonar-batch/src/main/java/org/sonar/batch/scm/DefaultBlameOutput.java b/sonar-batch/src/main/java/org/sonar/batch/scm/DefaultBlameOutput.java
index b95ba5d2178..4323e5cff92 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/scm/DefaultBlameOutput.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/scm/DefaultBlameOutput.java
@@ -20,25 +20,25 @@
package org.sonar.batch.scm;
import com.google.common.base.Preconditions;
+import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.sonar.api.batch.fs.InputFile;
import org.sonar.api.batch.scm.BlameCommand.BlameOutput;
import org.sonar.api.batch.scm.BlameLine;
-import org.sonar.api.batch.sensor.SensorContext;
-import org.sonar.api.measures.CoreMetrics;
import org.sonar.api.measures.Metric;
import org.sonar.api.measures.PropertiesBuilder;
-import org.sonar.api.utils.DateUtils;
+import org.sonar.batch.index.BatchResource;
+import org.sonar.batch.index.ResourceCache;
+import org.sonar.batch.protocol.output.BatchReport;
+import org.sonar.batch.protocol.output.BatchReport.Scm.Builder;
+import org.sonar.batch.protocol.output.BatchReportWriter;
import org.sonar.batch.util.ProgressReport;
import javax.annotation.Nullable;
import java.text.Normalizer;
-import java.util.Date;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
+import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.regex.Pattern;
@@ -49,14 +49,16 @@ class DefaultBlameOutput implements BlameOutput {
private static final Pattern NON_ASCII_CHARS = Pattern.compile("[^\\x00-\\x7F]");
private static final Pattern ACCENT_CODES = Pattern.compile("\\p{InCombiningDiacriticalMarks}+");
- private final SensorContext context;
+ private final BatchReportWriter writer;
+ private final ResourceCache componentCache;
private final Set<InputFile> allFilesToBlame = new HashSet<InputFile>();
private ProgressReport progressReport;
private int count;
private int total;
- DefaultBlameOutput(SensorContext context, List<InputFile> filesToBlame) {
- this.context = context;
+ DefaultBlameOutput(BatchReportWriter writer, ResourceCache componentCache, List<InputFile> filesToBlame) {
+ this.writer = writer;
+ this.componentCache = componentCache;
this.allFilesToBlame.addAll(filesToBlame);
count = 0;
total = filesToBlame.size();
@@ -75,24 +77,45 @@ class DefaultBlameOutput implements BlameOutput {
return;
}
- PropertiesBuilder<Integer, String> authors = propertiesBuilder(CoreMetrics.SCM_AUTHORS_BY_LINE);
- PropertiesBuilder<Integer, String> dates = propertiesBuilder(CoreMetrics.SCM_LAST_COMMIT_DATETIMES_BY_LINE);
- PropertiesBuilder<Integer, String> revisions = propertiesBuilder(CoreMetrics.SCM_REVISIONS_BY_LINE);
+ BatchResource batchComponent = componentCache.get(file);
+ Builder scmBuilder = BatchReport.Scm.newBuilder();
+ scmBuilder.setComponentRef(batchComponent.batchId());
+ Map<String, Integer> changesetsIdByRevision = new HashMap<>();
- int lineNumber = 1;
for (BlameLine line : lines) {
- authors.add(lineNumber, normalizeString(line.author()));
- Date date = line.date();
- dates.add(lineNumber, date != null ? DateUtils.formatDateTime(date) : "");
- revisions.add(lineNumber, line.revision());
- lineNumber++;
+ if (StringUtils.isNotBlank(line.revision())) {
+ Integer changesetId = changesetsIdByRevision.get(line.revision());
+ if (changesetId == null) {
+ addChangeset(scmBuilder, line);
+ changesetId = scmBuilder.getChangesetCount() - 1;
+ changesetsIdByRevision.put(line.revision(), changesetId);
+ }
+ scmBuilder.addChangesetIndexByLine(changesetId);
+ } else {
+ addChangeset(scmBuilder, line);
+ }
}
- ScmSensor.saveMeasures(context, file, authors.buildData(), dates.buildData(), revisions.buildData());
+ writer.writeComponentScm(scmBuilder.build());
allFilesToBlame.remove(file);
count++;
progressReport.message(count + "/" + total + " files analyzed, last one was " + file.absolutePath());
}
+ private void addChangeset(Builder scmBuilder, BlameLine line) {
+ BatchReport.Scm.Changeset.Builder changesetBuilder = BatchReport.Scm.Changeset.newBuilder();
+ if (StringUtils.isNotBlank(line.revision())) {
+ changesetBuilder.setRevision(line.revision());
+ }
+ if (StringUtils.isNotBlank(line.author())) {
+ changesetBuilder.setAuthor(normalizeString(line.author()));
+ }
+ Date date = line.date();
+ if (date != null) {
+ changesetBuilder.setDate(date.getTime());
+ }
+ scmBuilder.addChangeset(changesetBuilder.build());
+ }
+
private String normalizeString(@Nullable String inputString) {
if (inputString == null) {
return "";
diff --git a/sonar-batch/src/main/java/org/sonar/batch/scm/ScmSensor.java b/sonar-batch/src/main/java/org/sonar/batch/scm/ScmSensor.java
index 09b74bc6a6a..700098ab142 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/scm/ScmSensor.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/scm/ScmSensor.java
@@ -30,10 +30,10 @@ import org.sonar.api.batch.fs.internal.DefaultInputFile;
import org.sonar.api.batch.sensor.Sensor;
import org.sonar.api.batch.sensor.SensorContext;
import org.sonar.api.batch.sensor.SensorDescriptor;
-import org.sonar.api.batch.sensor.measure.internal.DefaultMeasure;
-import org.sonar.api.measures.CoreMetrics;
+import org.sonar.batch.index.ResourceCache;
import org.sonar.batch.protocol.input.FileData;
import org.sonar.batch.protocol.input.ProjectRepositories;
+import org.sonar.batch.report.PublishReportJob;
import org.sonar.batch.scan.filesystem.InputFileMetadata;
import org.sonar.batch.scan.filesystem.InputPathCache;
@@ -49,14 +49,19 @@ public final class ScmSensor implements Sensor {
private final FileSystem fs;
private final ProjectRepositories projectReferentials;
private final InputPathCache inputPathCache;
+ private final ResourceCache resourceCache;
+ private final PublishReportJob publishReportJob;
public ScmSensor(ProjectDefinition projectDefinition, ScmConfiguration configuration,
- ProjectRepositories projectReferentials, FileSystem fs, InputPathCache inputPathCache) {
+ ProjectRepositories projectReferentials, FileSystem fs, InputPathCache inputPathCache, ResourceCache resourceCache,
+ PublishReportJob publishReportJob) {
this.projectDefinition = projectDefinition;
this.configuration = configuration;
this.projectReferentials = projectReferentials;
this.fs = fs;
this.inputPathCache = inputPathCache;
+ this.resourceCache = resourceCache;
+ this.publishReportJob = publishReportJob;
}
@Override
@@ -66,9 +71,9 @@ public final class ScmSensor implements Sensor {
}
@Override
- public void execute(final SensorContext context) {
+ public void execute(SensorContext context) {
if (configuration.isDisabled()) {
- LOG.info("SCM Sensor is disabled");
+ LOG.info("SCM Publisher is disabled");
return;
}
if (configuration.provider() == null) {
@@ -76,51 +81,32 @@ public final class ScmSensor implements Sensor {
return;
}
- List<InputFile> filesToBlame = collectFilesToBlame(context);
+ List<InputFile> filesToBlame = collectFilesToBlame();
if (!filesToBlame.isEmpty()) {
String key = configuration.provider().key();
LOG.info("SCM provider for this project is: " + key);
- DefaultBlameOutput output = new DefaultBlameOutput(context, filesToBlame);
+ DefaultBlameOutput output = new DefaultBlameOutput(publishReportJob.getWriter(), resourceCache, filesToBlame);
configuration.provider().blameCommand().blame(new DefaultBlameInput(fs, filesToBlame), output);
output.finish();
}
}
- private List<InputFile> collectFilesToBlame(final SensorContext context) {
+ private List<InputFile> collectFilesToBlame() {
if (configuration.forceReloadAll()) {
LOG.warn("Forced reloading of SCM data for all files.");
}
List<InputFile> filesToBlame = new LinkedList<InputFile>();
- for (InputFile f : fs.inputFiles(fs.predicates().all())) {
- if (!configuration.forceReloadAll()) {
- copyPreviousMeasuresForUnmodifiedFiles(context, filesToBlame, f);
- } else {
- filesToBlame.add(f);
- }
- }
- return filesToBlame;
- }
-
- private void copyPreviousMeasuresForUnmodifiedFiles(final SensorContext context, List<InputFile> filesToBlame, InputFile f) {
- FileData fileData = projectReferentials.fileData(projectDefinition.getKeyWithBranch(), f.relativePath());
-
- if (f.status() == Status.SAME && fileData != null) {
- if (fileData.needBlame()) {
+ for (InputFile f : inputPathCache.allFiles()) {
+ if (configuration.forceReloadAll()) {
addIfNotEmpty(filesToBlame, (DefaultInputFile) f);
} else {
- // Copy previous measures
- String scmAuthorsByLine = fileData.scmAuthorsByLine();
- String scmLastCommitDatetimesByLine = fileData.scmLastCommitDatetimesByLine();
- String scmRevisionsByLine = fileData.scmRevisionsByLine();
- if (scmAuthorsByLine != null
- && scmLastCommitDatetimesByLine != null
- && scmRevisionsByLine != null) {
- saveMeasures(context, f, scmAuthorsByLine, scmLastCommitDatetimesByLine, scmRevisionsByLine);
+ FileData fileData = projectReferentials.fileData(projectDefinition.getKeyWithBranch(), f.relativePath());
+ if (f.status() != Status.SAME || fileData == null || fileData.needBlame()) {
+ addIfNotEmpty(filesToBlame, (DefaultInputFile) f);
}
}
- } else {
- addIfNotEmpty(filesToBlame, (DefaultInputFile) f);
}
+ return filesToBlame;
}
private void addIfNotEmpty(List<InputFile> filesToBlame, DefaultInputFile f) {
@@ -130,24 +116,4 @@ public final class ScmSensor implements Sensor {
}
}
- static void saveMeasures(SensorContext context, InputFile f, String scmAuthorsByLine, String scmLastCommitDatetimesByLine, String scmRevisionsByLine) {
- ((DefaultMeasure<String>) context.<String>newMeasure()
- .onFile(f)
- .forMetric(CoreMetrics.SCM_AUTHORS_BY_LINE)
- .withValue(scmAuthorsByLine))
- .setFromCore()
- .save();
- ((DefaultMeasure<String>) context.<String>newMeasure()
- .onFile(f)
- .forMetric(CoreMetrics.SCM_LAST_COMMIT_DATETIMES_BY_LINE)
- .withValue(scmLastCommitDatetimesByLine))
- .setFromCore()
- .save();
- ((DefaultMeasure<String>) context.<String>newMeasure()
- .onFile(f)
- .forMetric(CoreMetrics.SCM_REVISIONS_BY_LINE)
- .withValue(scmRevisionsByLine))
- .setFromCore()
- .save();
- }
}
diff --git a/sonar-batch/src/test/java/org/sonar/batch/index/SourceDataFactoryTest.java b/sonar-batch/src/test/java/org/sonar/batch/index/SourceDataFactoryTest.java
index f55cd36f09f..a37bef0da56 100644
--- a/sonar-batch/src/test/java/org/sonar/batch/index/SourceDataFactoryTest.java
+++ b/sonar-batch/src/test/java/org/sonar/batch/index/SourceDataFactoryTest.java
@@ -38,6 +38,10 @@ import org.sonar.api.source.Symbol;
import org.sonar.batch.duplication.DuplicationCache;
import org.sonar.batch.highlighting.SyntaxHighlightingData;
import org.sonar.batch.highlighting.SyntaxHighlightingDataBuilder;
+import org.sonar.batch.protocol.output.BatchReport.Scm;
+import org.sonar.batch.protocol.output.BatchReport.Scm.Changeset;
+import org.sonar.batch.protocol.output.BatchReportWriter;
+import org.sonar.batch.report.PublishReportJob;
import org.sonar.batch.scan.filesystem.InputFileMetadata;
import org.sonar.batch.scan.measure.MeasureCache;
import org.sonar.batch.source.CodeColorizers;
@@ -59,17 +63,25 @@ public class SourceDataFactoryTest {
@Rule
public TemporaryFolder temp = new TemporaryFolder();
- MeasureCache measureCache = mock(MeasureCache.class);
- ComponentDataCache componentDataCache = mock(ComponentDataCache.class);
- DuplicationCache duplicationCache = mock(DuplicationCache.class);
- CodeColorizers colorizers = mock(CodeColorizers.class);
- DefaultInputFile inputFile;
- InputFileMetadata metadata;
- SourceDataFactory sut = new SourceDataFactory(measureCache, componentDataCache, duplicationCache, colorizers);
- FileSourceDb.Data.Builder output;
+ private MeasureCache measureCache = mock(MeasureCache.class);
+ private ComponentDataCache componentDataCache = mock(ComponentDataCache.class);
+ private DuplicationCache duplicationCache = mock(DuplicationCache.class);
+ private CodeColorizers colorizers = mock(CodeColorizers.class);
+ private DefaultInputFile inputFile;
+ private InputFileMetadata metadata;
+ private SourceDataFactory sut;
+ private FileSourceDb.Data.Builder output;
+ private File reportDir;
@Before
public void setUp() throws Exception {
+ PublishReportJob publishReportJob = mock(PublishReportJob.class);
+ reportDir = temp.newFolder();
+ when(publishReportJob.getReportDir()).thenReturn(reportDir);
+ ResourceCache resourceCache = new ResourceCache();
+ resourceCache.add(org.sonar.api.resources.File.create("src/Foo.java").setEffectiveKey("module_key:src/Foo.java"), null);
+ when(measureCache.byMetric(anyString(), anyString())).thenReturn(Collections.<Measure>emptyList());
+ sut = new SourceDataFactory(measureCache, componentDataCache, duplicationCache, colorizers, publishReportJob, resourceCache);
// generate a file with 3 lines
File baseDir = temp.newFolder();
DefaultFileSystem fs = new DefaultFileSystem(baseDir.toPath());
@@ -137,10 +149,39 @@ public class SourceDataFactoryTest {
}
@Test
+ public void applyScm() throws Exception {
+ BatchReportWriter writer = new BatchReportWriter(reportDir);
+ writer.writeComponentScm(Scm.newBuilder().setComponentRef(1)
+ .addChangeset(Changeset.newBuilder()
+ .setRevision("ABC")
+ .setAuthor("him")
+ .setDate(123456L)
+ .build())
+ .addChangeset(Changeset.newBuilder()
+ .build())
+ .addChangesetIndexByLine(0)
+ .addChangesetIndexByLine(1)
+ .addChangesetIndexByLine(0)
+ // This should never happens but here there is 4 data but inputfile has only 3 lines
+ .addChangesetIndexByLine(1)
+ .build());
+
+ sut.applyScm(inputFile, output);
+
+ FileSourceDb.Data data = output.build();
+ assertThat(data.getLines(0).getScmRevision()).isEqualTo("ABC");
+ assertThat(data.getLines(0).getScmAuthor()).isEqualTo("him");
+
+ assertThat(data.getLines(1).hasScmRevision()).isFalse();
+ assertThat(data.getLines(1).hasScmAuthor()).isFalse();
+
+ assertThat(data.getLines(2).getScmRevision()).isEqualTo("ABC");
+ assertThat(data.getLines(2).getScmAuthor()).isEqualTo("him");
+
+ }
+
+ @Test
public void applyLineMeasures() throws Exception {
- setupLineMeasure(CoreMetrics.SCM_AUTHORS_BY_LINE, "1=him;2=her");
- setupLineMeasure(CoreMetrics.SCM_LAST_COMMIT_DATETIMES_BY_LINE, "1=2014-10-11T16:44:02+0100;2=2014-10-12T16:44:02+0100;3=2014-10-13T16:44:02+0100");
- setupLineMeasure(CoreMetrics.SCM_REVISIONS_BY_LINE, "1=ABC;2=234;3=345");
setupLineMeasure(CoreMetrics.COVERAGE_LINE_HITS_DATA, "1=10;3=4");
setupLineMeasure(CoreMetrics.CONDITIONS_BY_LINE, "1=10;3=4");
setupLineMeasure(CoreMetrics.CONDITIONS_BY_LINE, "1=10;3=4");
@@ -157,15 +198,11 @@ public class SourceDataFactoryTest {
FileSourceDb.Data data = output.build();
assertThat(data.getLines(0).getUtLineHits()).isEqualTo(10);
assertThat(data.getLines(0).getItLineHits()).isEqualTo(11);
- assertThat(data.getLines(0).getScmRevision()).isEqualTo("ABC");
- assertThat(data.getLines(0).getScmAuthor()).isEqualTo("him");
assertThat(data.getLines(1).hasUtLineHits()).isFalse();
assertThat(data.getLines(1).getItLineHits()).isEqualTo(4);
- assertThat(data.getLines(1).getScmAuthor()).isEqualTo("her");
assertThat(data.getLines(2).getUtLineHits()).isEqualTo(4);
- assertThat(data.getLines(2).hasScmAuthor()).isFalse();
}
private void setupLineMeasure(Metric metric, String dataPerLine) {
diff --git a/sonar-batch/src/test/java/org/sonar/batch/mediumtest/preview/IncrementalModeMediumTest.java b/sonar-batch/src/test/java/org/sonar/batch/mediumtest/preview/IncrementalModeMediumTest.java
index ffc8451d9cb..6bffe47ace2 100644
--- a/sonar-batch/src/test/java/org/sonar/batch/mediumtest/preview/IncrementalModeMediumTest.java
+++ b/sonar-batch/src/test/java/org/sonar/batch/mediumtest/preview/IncrementalModeMediumTest.java
@@ -67,7 +67,7 @@ public class IncrementalModeMediumTest {
.activateRule(new ActiveRule("xoo", "OneIssuePerLine", null, "One issue per line", "MAJOR", null, "xoo"))
.activateRule(new ActiveRule("manual", "MyManualIssue", null, "My manual issue", "MAJOR", null, null))
.setPreviousAnalysisDate(new Date())
- .addFileData("sample", "src/sample.xoo", new FileData(DigestUtils.md5Hex(SAMPLE_CONTENT), false, null, null, null))
+ .addFileData("sample", "src/sample.xoo", new FileData(DigestUtils.md5Hex(SAMPLE_CONTENT), false))
.mockLineHashes("sample:src/sample.xoo",
new String[] {DigestUtils.md5Hex("Samplecontent"), DigestUtils.md5Hex("oldcode"), DigestUtils.md5Hex("4"), DigestUtils.md5Hex("lines")})
// Remote open issue => will be tracked and not new
diff --git a/sonar-batch/src/test/java/org/sonar/batch/mediumtest/scm/ScmMediumTest.java b/sonar-batch/src/test/java/org/sonar/batch/mediumtest/scm/ScmMediumTest.java
index 61cbf327eb6..7c80e0db6dd 100644
--- a/sonar-batch/src/test/java/org/sonar/batch/mediumtest/scm/ScmMediumTest.java
+++ b/sonar-batch/src/test/java/org/sonar/batch/mediumtest/scm/ScmMediumTest.java
@@ -28,13 +28,14 @@ import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.junit.rules.TemporaryFolder;
-import org.sonar.api.batch.fs.internal.DefaultInputFile;
-import org.sonar.api.batch.sensor.measure.internal.DefaultMeasure;
-import org.sonar.api.measures.CoreMetrics;
import org.sonar.batch.mediumtest.BatchMediumTester;
import org.sonar.batch.mediumtest.BatchMediumTester.TaskBuilder;
import org.sonar.batch.mediumtest.TaskResult;
import org.sonar.batch.protocol.input.FileData;
+import org.sonar.batch.protocol.output.BatchReport.Component;
+import org.sonar.batch.protocol.output.BatchReport.Scm;
+import org.sonar.batch.protocol.output.BatchReport.Scm.Changeset;
+import org.sonar.batch.protocol.output.BatchReportReader;
import org.sonar.xoo.XooPlugin;
import java.io.File;
@@ -55,7 +56,7 @@ public class ScmMediumTest {
public BatchMediumTester tester = BatchMediumTester.builder()
.registerPlugin("xoo", new XooPlugin())
.addDefaultQProfile("xoo", "Sonar Way")
- .addFileData("com.foo.project", "src/sample2.xoo", new FileData(DigestUtils.md5Hex(SAMPLE_XOO_CONTENT), false, "1=;2=", "1=;2=", "1=;2="))
+ .addFileData("com.foo.project", "src/sample2.xoo", new FileData(DigestUtils.md5Hex(SAMPLE_XOO_CONTENT), false))
.build();
@Before
@@ -86,17 +87,35 @@ public class ScmMediumTest {
.build())
.start();
- assertThat(result.measures()).hasSize(5);
+ Scm fileScm = getScm(baseDir, 0);
- assertThat(result.measures()).contains(new DefaultMeasure<Integer>()
- .forMetric(CoreMetrics.LINES)
- .onFile(new DefaultInputFile("com.foo.project", "src/sample.xoo"))
- .withValue(5));
+ assertThat(fileScm.getChangesetIndexByLineList()).hasSize(5);
- assertThat(result.measures()).contains(new DefaultMeasure<String>()
- .forMetric(CoreMetrics.SCM_AUTHORS_BY_LINE)
- .onFile(new DefaultInputFile("com.foo.project", "src/sample.xoo"))
- .withValue("1=;2=julien;3=julien;4=julien;5=simon"));
+ Changeset changesetLine1 = fileScm.getChangeset(fileScm.getChangesetIndexByLine(0));
+ assertThat(changesetLine1.hasAuthor()).isFalse();
+
+ Changeset changesetLine2 = fileScm.getChangeset(fileScm.getChangesetIndexByLine(1));
+ assertThat(changesetLine2.getAuthor()).isEqualTo("julien");
+
+ Changeset changesetLine3 = fileScm.getChangeset(fileScm.getChangesetIndexByLine(2));
+ assertThat(changesetLine3.getAuthor()).isEqualTo("julien");
+
+ Changeset changesetLine4 = fileScm.getChangeset(fileScm.getChangesetIndexByLine(3));
+ assertThat(changesetLine4.getAuthor()).isEqualTo("julien");
+
+ Changeset changesetLine5 = fileScm.getChangeset(fileScm.getChangesetIndexByLine(4));
+ assertThat(changesetLine5.getAuthor()).isEqualTo("simon");
+ }
+
+ private Scm getScm(File baseDir, int fileId) {
+ File reportDir = new File(baseDir, ".sonar/batch-report");
+ BatchReportReader reader = new BatchReportReader(reportDir);
+
+ Component project = reader.readComponent(reader.readMetadata().getRootComponentRef());
+ Component dir = reader.readComponent(project.getChildRef(0));
+ Component file = reader.readComponent(dir.getChildRef(fileId));
+ Scm fileScm = reader.readComponentScm(file.getRef());
+ return fileScm;
}
@Test
@@ -120,17 +139,14 @@ public class ScmMediumTest {
.build())
.start();
- // lines + qprofile
- assertThat(result.measures()).hasSize(2);
+ Scm fileScm = getScm(baseDir, 0);
+
+ assertThat(fileScm).isNull();
- assertThat(result.measures()).contains(new DefaultMeasure<Integer>()
- .forMetric(CoreMetrics.LINES)
- .onFile(new DefaultInputFile("com.foo.project", "src/sample.xoo"))
- .withValue(1));
}
@Test
- public void dontFailIfMissingFile() throws IOException {
+ public void sample2_dont_need_blame() throws IOException {
File baseDir = prepareProject();
File xooFile = new File(baseDir, "src/sample2.xoo");
@@ -148,14 +164,26 @@ public class ScmMediumTest {
.put("sonar.scm.provider", "xoo")
.build())
.start();
+
+ Scm file1Scm = getScm(baseDir, 0);
+ assertThat(file1Scm).isNotNull();
+
+ Scm file2Scm = getScm(baseDir, 1);
+ assertThat(file2Scm).isNull();
}
@Test
- public void copyPreviousMeasuresOrForceReload() throws IOException {
+ public void forceReload() throws IOException {
File baseDir = prepareProject();
File xooFileNoScm = new File(baseDir, "src/sample2.xoo");
FileUtils.write(xooFileNoScm, SAMPLE_XOO_CONTENT);
+ File xooScmFile = new File(baseDir, "src/sample2.xoo.scm");
+ FileUtils.write(xooScmFile,
+ // revision,author,dateTime
+ "1,foo,2013-01-04\n" +
+ "1,bar,2013-01-04\n"
+ );
TaskBuilder taskBuilder = tester.newTask()
.properties(ImmutableMap.<String, String>builder()
@@ -167,38 +195,17 @@ public class ScmMediumTest {
.put("sonar.projectDescription", "Description of Foo Project")
.put("sonar.sources", "src")
.put("sonar.scm.provider", "xoo")
+ // Force reload
+ .put("sonar.scm.forceReloadAll", "true")
.build());
- TaskResult result = taskBuilder.start();
-
- assertThat(result.measures()).hasSize(1 + 2 * 4);
+ taskBuilder.start();
- assertThat(result.measures()).contains(new DefaultMeasure<Integer>()
- .forMetric(CoreMetrics.LINES)
- .onFile(new DefaultInputFile("com.foo.project", "src/sample2.xoo"))
- .withValue(2));
+ Scm file1Scm = getScm(baseDir, 0);
+ assertThat(file1Scm).isNotNull();
- assertThat(result.measures()).contains(new DefaultMeasure<String>()
- .forMetric(CoreMetrics.SCM_AUTHORS_BY_LINE)
- .onFile(new DefaultInputFile("com.foo.project", "src/sample2.xoo"))
- .withValue("1=;2="));
-
- // Force reload
- File xooScmFile = new File(baseDir, "src/sample2.xoo.scm");
- FileUtils.write(xooScmFile,
- // revision,author,dateTime
- "1,foo,2013-01-04\n" +
- "1,bar,2013-01-04\n"
- );
-
- result = taskBuilder
- .property("sonar.scm.forceReloadAll", "true")
- .start();
-
- assertThat(result.measures()).contains(new DefaultMeasure<String>()
- .forMetric(CoreMetrics.SCM_AUTHORS_BY_LINE)
- .onFile(new DefaultInputFile("com.foo.project", "src/sample2.xoo"))
- .withValue("1=foo;2=bar"));
+ Scm file2Scm = getScm(baseDir, 1);
+ assertThat(file2Scm).isNotNull();
}
@Test
@@ -206,7 +213,7 @@ public class ScmMediumTest {
File baseDir = prepareProject();
- TaskResult result = tester.newTask()
+ tester.newTask()
.properties(ImmutableMap.<String, String>builder()
.put("sonar.task", "scan")
.put("sonar.projectBaseDir", baseDir.getAbsolutePath())
@@ -219,17 +226,8 @@ public class ScmMediumTest {
.build())
.start();
- assertThat(result.measures()).hasSize(5);
-
- assertThat(result.measures()).contains(new DefaultMeasure<Integer>()
- .forMetric(CoreMetrics.LINES)
- .onFile(new DefaultInputFile("com.foo.project", "src/sample.xoo"))
- .withValue(5));
-
- assertThat(result.measures()).contains(new DefaultMeasure<String>()
- .forMetric(CoreMetrics.SCM_AUTHORS_BY_LINE)
- .onFile(new DefaultInputFile("com.foo.project", "src/sample.xoo"))
- .withValue("1=;2=julien;3=julien;4=julien;5=simon"));
+ Scm file1Scm = getScm(baseDir, 0);
+ assertThat(file1Scm).isNotNull();
}
@Test
@@ -238,7 +236,7 @@ public class ScmMediumTest {
File baseDir = prepareProject();
new File(baseDir, ".xoo").createNewFile();
- TaskResult result = tester.newTask()
+ tester.newTask()
.properties(ImmutableMap.<String, String>builder()
.put("sonar.task", "scan")
.put("sonar.projectBaseDir", baseDir.getAbsolutePath())
@@ -250,17 +248,8 @@ public class ScmMediumTest {
.build())
.start();
- assertThat(result.measures()).hasSize(5);
-
- assertThat(result.measures()).contains(new DefaultMeasure<Integer>()
- .forMetric(CoreMetrics.LINES)
- .onFile(new DefaultInputFile("com.foo.project", "src/sample.xoo"))
- .withValue(5));
-
- assertThat(result.measures()).contains(new DefaultMeasure<String>()
- .forMetric(CoreMetrics.SCM_AUTHORS_BY_LINE)
- .onFile(new DefaultInputFile("com.foo.project", "src/sample.xoo"))
- .withValue("1=;2=julien;3=julien;4=julien;5=simon"));
+ Scm file1Scm = getScm(baseDir, 0);
+ assertThat(file1Scm).isNotNull();
}
private File prepareProject() throws IOException {
@@ -274,10 +263,10 @@ public class ScmMediumTest {
FileUtils.write(xooScmFile1,
// revision,author,dateTime
"1,,2013-01-04\n" +
- "1,julien,2013-01-04\n" +
- "2,julien,2013-02-03\n" +
- "2,julien,2013-02-03\n" +
- "3,simon,2013-03-04\n"
+ "2,julien,2013-01-04\n" +
+ "3,julien,2013-02-03\n" +
+ "3,julien,2013-02-03\n" +
+ "4,simon,2013-03-04\n"
);
return baseDir;
diff --git a/sonar-batch/src/test/java/org/sonar/batch/qualitygate/QualityGateVerifierTest.java b/sonar-batch/src/test/java/org/sonar/batch/qualitygate/QualityGateVerifierTest.java
index 26447e6e792..ca89fe8ccae 100644
--- a/sonar-batch/src/test/java/org/sonar/batch/qualitygate/QualityGateVerifierTest.java
+++ b/sonar-batch/src/test/java/org/sonar/batch/qualitygate/QualityGateVerifierTest.java
@@ -344,12 +344,12 @@ public class QualityGateVerifierTest {
@Test(expected = NotImplementedException.class)
public void shouldNotAllowPeriodVariationAlertOnStringMetric() {
- Measure measure = new Measure(CoreMetrics.SCM_AUTHORS_BY_LINE, 100d);
+ Measure measure = new Measure(CoreMetrics.NCLOC_LANGUAGE_DISTRIBUTION, 100d);
measure.setVariation1(50d);
- when(context.getMeasure(CoreMetrics.SCM_AUTHORS_BY_LINE)).thenReturn(measure);
+ when(context.getMeasure(CoreMetrics.NCLOC_LANGUAGE_DISTRIBUTION)).thenReturn(measure);
ArrayList<ResolvedCondition> conditions = Lists.newArrayList(
- mockCondition(CoreMetrics.SCM_AUTHORS_BY_LINE, QualityGateConditionDto.OPERATOR_GREATER_THAN, null, "30", 1)
+ mockCondition(CoreMetrics.NCLOC_LANGUAGE_DISTRIBUTION, QualityGateConditionDto.OPERATOR_GREATER_THAN, null, "30", 1)
);
when(qualityGate.conditions()).thenReturn(conditions);
diff --git a/sonar-batch/src/test/java/org/sonar/batch/report/PublishReportJobTest.java b/sonar-batch/src/test/java/org/sonar/batch/report/PublishReportJobTest.java
index 2da52bd2f3d..a636a5386df 100644
--- a/sonar-batch/src/test/java/org/sonar/batch/report/PublishReportJobTest.java
+++ b/sonar-batch/src/test/java/org/sonar/batch/report/PublishReportJobTest.java
@@ -23,16 +23,19 @@ import org.junit.Before;
import org.junit.Test;
import org.slf4j.Logger;
import org.sonar.api.CoreProperties;
+import org.sonar.api.batch.bootstrap.ProjectDefinition;
+import org.sonar.api.batch.bootstrap.ProjectReactor;
import org.sonar.api.config.Settings;
import org.sonar.api.platform.Server;
-import org.sonar.api.resources.Project;
import org.sonar.api.utils.TempFolder;
import org.sonar.batch.bootstrap.DefaultAnalysisMode;
import org.sonar.batch.bootstrap.ServerClient;
import org.sonar.batch.index.ResourceCache;
import org.sonar.jpa.test.AbstractDbUnitTestCase;
-import static org.mockito.Mockito.*;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
public class PublishReportJobTest extends AbstractDbUnitTestCase {
@@ -40,17 +43,20 @@ public class PublishReportJobTest extends AbstractDbUnitTestCase {
ResourceCache resourceCache = mock(ResourceCache.class);
+ private ProjectReactor reactor;
+
@Before
public void setUp() {
mode = mock(DefaultAnalysisMode.class);
+ reactor = mock(ProjectReactor.class);
+ when(reactor.getRoot()).thenReturn(ProjectDefinition.create().setKey("struts"));
}
@Test
public void should_log_successful_analysis() throws Exception {
Settings settings = new Settings();
settings.setProperty(CoreProperties.SERVER_BASE_URL, "http://myserver/");
- Project project = new Project("struts");
- PublishReportJob job = new PublishReportJob(settings, mock(ServerClient.class), mock(Server.class), project, mode, mock(TempFolder.class));
+ PublishReportJob job = new PublishReportJob(settings, mock(ServerClient.class), mock(Server.class), reactor, mode, mock(TempFolder.class), new ReportPublisher[0]);
Logger logger = mock(Logger.class);
job.logSuccess(logger);
@@ -63,8 +69,7 @@ public class PublishReportJobTest extends AbstractDbUnitTestCase {
public void should_log_successful_preview_analysis() throws Exception {
Settings settings = new Settings();
when(mode.isPreview()).thenReturn(true);
- Project project = new Project("struts");
- PublishReportJob job = new PublishReportJob(settings, mock(ServerClient.class), mock(Server.class), project, mode, mock(TempFolder.class));
+ PublishReportJob job = new PublishReportJob(settings, mock(ServerClient.class), mock(Server.class), reactor, mode, mock(TempFolder.class), new ReportPublisher[0]);
Logger logger = mock(Logger.class);
job.logSuccess(logger);
diff --git a/sonar-batch/src/test/java/org/sonar/batch/scan/ProjectReactorReadyTest.java b/sonar-batch/src/test/java/org/sonar/batch/scan/ProjectReactorReadyTest.java
index 8ab69d7fec7..63f2377e67e 100644
--- a/sonar-batch/src/test/java/org/sonar/batch/scan/ProjectReactorReadyTest.java
+++ b/sonar-batch/src/test/java/org/sonar/batch/scan/ProjectReactorReadyTest.java
@@ -22,7 +22,6 @@ package org.sonar.batch.scan;
import org.junit.Test;
import org.sonar.api.batch.bootstrap.ProjectBuilder;
import org.sonar.api.batch.bootstrap.ProjectReactor;
-import org.sonar.batch.repository.ProjectScmRepositoryLoader;
import static org.mockito.Mockito.mock;
@@ -31,14 +30,13 @@ public class ProjectReactorReadyTest {
public void should_do_nothing() {
// it's only a barrier
ProjectReactorReady barrier = new ProjectReactorReady(mock(ProjectExclusions.class), mock(ProjectReactor.class),
- new ProjectBuilder[] {mock(ProjectBuilder.class)}, mock(ProjectReactorValidator.class), mock(ProjectScmRepositoryLoader.class));
+ new ProjectBuilder[] {mock(ProjectBuilder.class)}, mock(ProjectReactorValidator.class));
barrier.start();
}
@Test
public void project_builders_should_be_optional() {
- ProjectReactorReady barrier = new ProjectReactorReady(mock(ProjectExclusions.class), mock(ProjectReactor.class), mock(ProjectReactorValidator.class),
- mock(ProjectScmRepositoryLoader.class));
+ ProjectReactorReady barrier = new ProjectReactorReady(mock(ProjectExclusions.class), mock(ProjectReactor.class), mock(ProjectReactorValidator.class));
barrier.start();
}
}
diff --git a/sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/StatusDetectionTest.java b/sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/StatusDetectionTest.java
index 261ff3b8a2c..cc5feed7883 100644
--- a/sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/StatusDetectionTest.java
+++ b/sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/StatusDetectionTest.java
@@ -30,8 +30,8 @@ public class StatusDetectionTest {
@Test
public void detect_status() throws Exception {
ProjectRepositories ref = new ProjectRepositories();
- ref.addFileData("foo", "src/Foo.java", new FileData("ABCDE", true, null, null, null));
- ref.addFileData("foo", "src/Bar.java", new FileData("FGHIJ", true, null, null, null));
+ ref.addFileData("foo", "src/Foo.java", new FileData("ABCDE", true));
+ ref.addFileData("foo", "src/Bar.java", new FileData("FGHIJ", true));
StatusDetection statusDetection = new StatusDetection(ref);
assertThat(statusDetection.status("foo", "src/Foo.java", "ABCDE")).isEqualTo(InputFile.Status.SAME);
diff --git a/sonar-batch/src/test/java/org/sonar/batch/scm/DefaultBlameOutputTest.java b/sonar-batch/src/test/java/org/sonar/batch/scm/DefaultBlameOutputTest.java
index 3b5632ccb7e..a92b20382dd 100644
--- a/sonar-batch/src/test/java/org/sonar/batch/scm/DefaultBlameOutputTest.java
+++ b/sonar-batch/src/test/java/org/sonar/batch/scm/DefaultBlameOutputTest.java
@@ -37,7 +37,7 @@ public class DefaultBlameOutputTest {
public void shouldNotFailIfNotSameNumberOfLines() {
InputFile file = new DefaultInputFile("foo", "src/main/java/Foo.java").setLines(10);
- new DefaultBlameOutput(null, Arrays.asList(file)).blameResult(file, Arrays.asList(new BlameLine().revision("1").author("guy")));
+ new DefaultBlameOutput(null, null, Arrays.asList(file)).blameResult(file, Arrays.asList(new BlameLine().revision("1").author("guy")));
}
@Test
@@ -47,7 +47,7 @@ public class DefaultBlameOutputTest {
thrown.expect(IllegalArgumentException.class);
thrown.expectMessage("It was not expected to blame file src/main/java/Foo.java");
- new DefaultBlameOutput(null, Arrays.<InputFile>asList(new DefaultInputFile("foo", "src/main/java/Foo2.java")))
+ new DefaultBlameOutput(null, null, Arrays.<InputFile>asList(new DefaultInputFile("foo", "src/main/java/Foo2.java")))
.blameResult(file, Arrays.asList(new BlameLine().revision("1").author("guy")));
}
diff --git a/sonar-plugin-api/src/test/java/org/sonar/api/resources/CoreMetricsTest.java b/sonar-plugin-api/src/test/java/org/sonar/api/resources/CoreMetricsTest.java
index c5db06856fe..0dcbda870b1 100644
--- a/sonar-plugin-api/src/test/java/org/sonar/api/resources/CoreMetricsTest.java
+++ b/sonar-plugin-api/src/test/java/org/sonar/api/resources/CoreMetricsTest.java
@@ -32,7 +32,7 @@ public class CoreMetricsTest {
@Test
public void read_metrics_from_class_reflection() {
List<Metric> metrics = CoreMetrics.getMetrics();
- assertThat(metrics).hasSize(142);
+ assertThat(metrics.size()).isGreaterThan(100);
assertThat(metrics).contains(CoreMetrics.NCLOC, CoreMetrics.DIRECTORIES);
}