Skip to content

Commit

Permalink
SONAR-6824 Use SCM Info repo
Browse files Browse the repository at this point in the history
  • Loading branch information
julienlancelot committed Oct 27, 2015
1 parent 9afa627 commit 2e66147
Show file tree
Hide file tree
Showing 2 changed files with 35 additions and 66 deletions.
Expand Up @@ -21,26 +21,25 @@


import com.google.common.base.Optional; import com.google.common.base.Optional;
import org.sonar.api.measures.CoreMetrics; import org.sonar.api.measures.CoreMetrics;
import org.sonar.batch.protocol.output.BatchReport;
import org.sonar.server.computation.batch.BatchReportReader;
import org.sonar.server.computation.component.Component; import org.sonar.server.computation.component.Component;
import org.sonar.server.computation.component.CrawlerDepthLimit; import org.sonar.server.computation.component.CrawlerDepthLimit;
import org.sonar.server.computation.component.PathAwareVisitorAdapter; import org.sonar.server.computation.component.PathAwareVisitorAdapter;
import org.sonar.server.computation.measure.Measure; import org.sonar.server.computation.measure.Measure;
import org.sonar.server.computation.measure.MeasureRepository; import org.sonar.server.computation.measure.MeasureRepository;
import org.sonar.server.computation.metric.Metric; import org.sonar.server.computation.metric.Metric;
import org.sonar.server.computation.metric.MetricRepository; import org.sonar.server.computation.metric.MetricRepository;
import org.sonar.server.computation.scm.ScmInfo;
import org.sonar.server.computation.scm.ScmInfoRepository;


import static org.sonar.server.computation.component.ComponentVisitor.Order.POST_ORDER; import static org.sonar.server.computation.component.ComponentVisitor.Order.POST_ORDER;


public class LastCommitVisitor extends PathAwareVisitorAdapter<LastCommitVisitor.LastCommit> { public class LastCommitVisitor extends PathAwareVisitorAdapter<LastCommitVisitor.LastCommit> {


private final BatchReportReader reportReader;
private final MeasureRepository measureRepository; private final MeasureRepository measureRepository;
private final ScmInfoRepository scmInfoRepository;
private final Metric lastCommitDateMetric; private final Metric lastCommitDateMetric;


public LastCommitVisitor(BatchReportReader reportReader, MetricRepository metricRepository, public LastCommitVisitor(MetricRepository metricRepository, MeasureRepository measureRepository, ScmInfoRepository scmInfoRepository) {
MeasureRepository measureRepository) {
super(CrawlerDepthLimit.LEAVES, POST_ORDER, new SimpleStackElementFactory<LastCommit>() { super(CrawlerDepthLimit.LEAVES, POST_ORDER, new SimpleStackElementFactory<LastCommit>() {
@Override @Override
public LastCommit createForAny(Component component) { public LastCommit createForAny(Component component) {
Expand All @@ -53,8 +52,8 @@ public LastCommit createForProjectView(Component projectView) {
return null; return null;
} }
}); });
this.reportReader = reportReader;
this.measureRepository = measureRepository; this.measureRepository = measureRepository;
this.scmInfoRepository = scmInfoRepository;
this.lastCommitDateMetric = metricRepository.getByKey(CoreMetrics.LAST_COMMIT_DATE_KEY); this.lastCommitDateMetric = metricRepository.getByKey(CoreMetrics.LAST_COMMIT_DATE_KEY);
} }


Expand All @@ -79,21 +78,10 @@ public void visitFile(Component file, Path<LastCommit> path) {
// since previous analysis (optimization to decrease execution of blame commands). In this case // since previous analysis (optimization to decrease execution of blame commands). In this case
// the date is loaded from database, as it did not change from previous analysis. // the date is loaded from database, as it did not change from previous analysis.


// TODO We should use ScmInfoRepository instead of reading the report Optional<ScmInfo> scmInfoOptional = scmInfoRepository.getScmInfo(file);
// (but should only be done when the repo is only used once per component, if (scmInfoOptional.isPresent()) {
// as it's done with ComponentIssuesRepository, to not increase number of calls to file_sources) ScmInfo scmInfo = scmInfoOptional.get();
BatchReport.Changesets changesets = reportReader.readChangesets(file.getReportAttributes().getRef()); path.current().addDate(scmInfo.getLatestChangeset().getDate());
if (changesets == null) {
Optional<Measure> baseMeasure = measureRepository.getBaseMeasure(file, lastCommitDateMetric);
if (baseMeasure.isPresent()) {
path.current().addDate(baseMeasure.get().getLongValue());
}
} else {
for (BatchReport.Changesets.Changeset changeset : changesets.getChangesetList()) {
if (changeset.hasDate()) {
path.current().addDate(changeset.getDate());
}
}
} }
saveAndAggregate(file, path); saveAndAggregate(file, path);
} }
Expand Down
Expand Up @@ -24,8 +24,6 @@
import org.junit.Rule; import org.junit.Rule;
import org.junit.Test; import org.junit.Test;
import org.sonar.api.measures.CoreMetrics; import org.sonar.api.measures.CoreMetrics;
import org.sonar.batch.protocol.output.BatchReport;
import org.sonar.server.computation.batch.BatchReportReaderRule;
import org.sonar.server.computation.batch.TreeRootHolderRule; import org.sonar.server.computation.batch.TreeRootHolderRule;
import org.sonar.server.computation.component.Component; import org.sonar.server.computation.component.Component;
import org.sonar.server.computation.component.ComponentVisitor; import org.sonar.server.computation.component.ComponentVisitor;
Expand All @@ -36,6 +34,8 @@
import org.sonar.server.computation.measure.Measure; import org.sonar.server.computation.measure.Measure;
import org.sonar.server.computation.measure.MeasureRepositoryRule; import org.sonar.server.computation.measure.MeasureRepositoryRule;
import org.sonar.server.computation.metric.MetricRepositoryRule; import org.sonar.server.computation.metric.MetricRepositoryRule;
import org.sonar.server.computation.scm.Changeset;
import org.sonar.server.computation.scm.ScmInfoRepositoryRule;


import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
import static org.sonar.api.measures.CoreMetrics.LAST_COMMIT_DATE_KEY; import static org.sonar.api.measures.CoreMetrics.LAST_COMMIT_DATE_KEY;
Expand All @@ -62,16 +62,16 @@ public class LastCommitVisitorTest {
@Rule @Rule
public TreeRootHolderRule treeRootHolder = new TreeRootHolderRule(); public TreeRootHolderRule treeRootHolder = new TreeRootHolderRule();


@Rule
public BatchReportReaderRule reportReader = new BatchReportReaderRule();

@Rule @Rule
public MetricRepositoryRule metricRepository = new MetricRepositoryRule() public MetricRepositoryRule metricRepository = new MetricRepositoryRule()
.add(CoreMetrics.LAST_COMMIT_DATE); .add(CoreMetrics.LAST_COMMIT_DATE);


@Rule @Rule
public MeasureRepositoryRule measureRepository = MeasureRepositoryRule.create(treeRootHolder, metricRepository); public MeasureRepositoryRule measureRepository = MeasureRepositoryRule.create(treeRootHolder, metricRepository);


@Rule
public ScmInfoRepositoryRule scmInfoRepository = new ScmInfoRepositoryRule();

@Test @Test
public void aggregate_date_of_last_commit_to_directories_and_project() { public void aggregate_date_of_last_commit_to_directories_and_project() {
final long FILE_1_DATE = 1_100_000_000_000L; final long FILE_1_DATE = 1_100_000_000_000L;
Expand All @@ -81,7 +81,7 @@ public void aggregate_date_of_last_commit_to_directories_and_project() {
final long FILE_3_DATE = 1_300_000_000_000L; final long FILE_3_DATE = 1_300_000_000_000L;


// simulate the output of visitFile() // simulate the output of visitFile()
LastCommitVisitor visitor = new LastCommitVisitor(reportReader, metricRepository, measureRepository) { LastCommitVisitor visitor = new LastCommitVisitor(metricRepository, measureRepository, scmInfoRepository) {
@Override @Override
public void visitFile(Component file, Path<LastCommit> path) { public void visitFile(Component file, Path<LastCommit> path) {
long fileDate; long fileDate;
Expand Down Expand Up @@ -168,7 +168,7 @@ public void aggregate_date_of_last_commit_to_views() {
measureRepository.addRawMeasure(PROJECT_2_REF, LAST_COMMIT_DATE_KEY, newMeasureBuilder().create(PROJECT_2_DATE)); measureRepository.addRawMeasure(PROJECT_2_REF, LAST_COMMIT_DATE_KEY, newMeasureBuilder().create(PROJECT_2_DATE));
measureRepository.addRawMeasure(PROJECT_3_REF, LAST_COMMIT_DATE_KEY, newMeasureBuilder().create(PROJECT_3_DATE)); measureRepository.addRawMeasure(PROJECT_3_REF, LAST_COMMIT_DATE_KEY, newMeasureBuilder().create(PROJECT_3_DATE));


VisitorsCrawler underTest = new VisitorsCrawler(Lists.<ComponentVisitor>newArrayList(new LastCommitVisitor(reportReader, metricRepository, measureRepository))); VisitorsCrawler underTest = new VisitorsCrawler(Lists.<ComponentVisitor>newArrayList(new LastCommitVisitor(metricRepository, measureRepository, scmInfoRepository)));
underTest.visit(view); underTest.visit(view);


// second level of sub-views // second level of sub-views
Expand All @@ -183,64 +183,39 @@ public void aggregate_date_of_last_commit_to_views() {
} }


@Test @Test
public void compute_date_of_file_from_blame_info_of_report() throws Exception { public void compute_date_of_file_from_scm_repo() throws Exception {
VisitorsCrawler underTest = new VisitorsCrawler(Lists.<ComponentVisitor>newArrayList(new LastCommitVisitor(reportReader, metricRepository, measureRepository))); VisitorsCrawler underTest = new VisitorsCrawler(Lists.<ComponentVisitor>newArrayList(new LastCommitVisitor(metricRepository, measureRepository, scmInfoRepository)));


BatchReport.Changesets changesets = BatchReport.Changesets.newBuilder() scmInfoRepository.setScmInfo(FILE_1_REF,
.setComponentRef(FILE_1_REF) Changeset.newChangesetBuilder()
.addChangeset(BatchReport.Changesets.Changeset.newBuilder()
.setAuthor("john") .setAuthor("john")
.setDate(1_500_000_000_000L) .setDate(1_500_000_000_000L)
.setRevision("rev-1") .setRevision("rev-1")
.build()) .build(),
.addChangeset(BatchReport.Changesets.Changeset.newBuilder() Changeset.newChangesetBuilder()
.setAuthor("tom") .setAuthor("tom")
// this is the most recent change // this is the most recent change
.setDate(1_600_000_000_000L) .setDate(1_600_000_000_000L)
.setRevision("rev-2") .setRevision("rev-2")
.build()) .build(),
.addChangeset(BatchReport.Changesets.Changeset.newBuilder() Changeset.newChangesetBuilder()
.setAuthor("john") .setAuthor("john")
.setDate(1_500_000_000_000L) .setDate(1_500_000_000_000L)
.setRevision("rev-1") .setRevision("rev-1")
.build()) .build()
.addChangesetIndexByLine(0) );
.build();
reportReader.putChangesets(changesets);
ReportComponent file = createFileComponent(FILE_1_REF);
treeRootHolder.setRoot(file);

underTest.visit(file);

assertDate(FILE_1_REF, 1_600_000_000_000L);
}

private void assertDate(int componentRef, long expectedDate) {
Optional<Measure> measure = measureRepository.getAddedRawMeasure(componentRef, LAST_COMMIT_DATE_KEY);
assertThat(measure.isPresent()).isTrue();
assertThat(measure.get().getLongValue()).isEqualTo(expectedDate);
}


/**
* When the file was not changed since previous analysis, than the report may not contain
* the SCM blame information. In this case the date of last commit is loaded
* from the base measure of previous analysis, directly from database
*/
@Test
public void reuse_date_of_previous_analysis_if_blame_info_is_not_in_report() throws Exception {
VisitorsCrawler underTest = new VisitorsCrawler(Lists.<ComponentVisitor>newArrayList(new LastCommitVisitor(reportReader, metricRepository, measureRepository)));
ReportComponent file = createFileComponent(FILE_1_REF); ReportComponent file = createFileComponent(FILE_1_REF);
treeRootHolder.setRoot(file); treeRootHolder.setRoot(file);
measureRepository.addBaseMeasure(FILE_1_REF, LAST_COMMIT_DATE_KEY, newMeasureBuilder().create(1_500_000_000L));


underTest.visit(file); underTest.visit(file);


assertDate(FILE_1_REF, 1_500_000_000L); assertDate(FILE_1_REF, 1_600_000_000_000L);
} }


@Test @Test
public void date_is_not_computed_on_file_if_blame_is_not_in_report_nor_in_previous_analysis() throws Exception { public void date_is_not_computed_on_file_if_blame_is_not_in_scm_repo() throws Exception {
VisitorsCrawler underTest = new VisitorsCrawler(Lists.<ComponentVisitor>newArrayList(new LastCommitVisitor(reportReader, metricRepository, measureRepository))); VisitorsCrawler underTest = new VisitorsCrawler(Lists.<ComponentVisitor>newArrayList(new LastCommitVisitor(metricRepository, measureRepository, scmInfoRepository)));
ReportComponent file = createFileComponent(FILE_1_REF); ReportComponent file = createFileComponent(FILE_1_REF);
treeRootHolder.setRoot(file); treeRootHolder.setRoot(file);


Expand All @@ -250,6 +225,12 @@ public void date_is_not_computed_on_file_if_blame_is_not_in_report_nor_in_previo
assertThat(measure.isPresent()).isFalse(); assertThat(measure.isPresent()).isFalse();
} }


private void assertDate(int componentRef, long expectedDate) {
Optional<Measure> measure = measureRepository.getAddedRawMeasure(componentRef, LAST_COMMIT_DATE_KEY);
assertThat(measure.isPresent()).isTrue();
assertThat(measure.get().getLongValue()).isEqualTo(expectedDate);
}

private ReportComponent createFileComponent(int fileRef) { private ReportComponent createFileComponent(int fileRef) {
return ReportComponent.builder(FILE, fileRef).setFileAttributes(new FileAttributes(false, "js")).build(); return ReportComponent.builder(FILE, fileRef).setFileAttributes(new FileAttributes(false, "js")).build();
} }
Expand Down

0 comments on commit 2e66147

Please sign in to comment.