import com.google.common.base.Optional;
import org.sonar.api.measures.CoreMetrics;
-import org.sonar.api.utils.System2;
import org.sonar.batch.protocol.output.BatchReport;
import org.sonar.server.computation.batch.BatchReportReader;
import org.sonar.server.computation.component.Component;
public class LastCommitVisitor extends PathAwareVisitorAdapter<LastCommitVisitor.LastCommit> {
- private static final long MILLISECONDS_PER_DAY = 1000L * 60 * 60 * 24;
-
private final BatchReportReader reportReader;
private final MeasureRepository measureRepository;
private final Metric lastCommitDateMetric;
- private final Metric daysSinceLastCommitDateMetric;
- private final System2 system2;
public LastCommitVisitor(BatchReportReader reportReader, MetricRepository metricRepository,
- MeasureRepository measureRepository, System2 system2) {
+ MeasureRepository measureRepository) {
super(CrawlerDepthLimit.LEAVES, POST_ORDER, new SimpleStackElementFactory<LastCommit>() {
@Override
public LastCommit createForAny(Component component) {
});
this.reportReader = reportReader;
this.measureRepository = measureRepository;
- this.system2 = system2;
this.lastCommitDateMetric = metricRepository.getByKey(CoreMetrics.LAST_COMMIT_DATE_KEY);
- this.daysSinceLastCommitDateMetric = metricRepository.getByKey(CoreMetrics.DAYS_SINCE_LAST_COMMIT_KEY);
}
@Override
long maxDate = path.current().getDate();
if (maxDate > 0L) {
measureRepository.add(component, lastCommitDateMetric, Measure.newMeasureBuilder().create(maxDate));
- measureRepository.add(component, daysSinceLastCommitDateMetric, Measure.newMeasureBuilder().create(daysBetween(system2.now(), maxDate)));
if (!path.isRoot()) {
path.parent().addDate(maxDate);
}
}
- private static int daysBetween(long d1, long d2) {
- // limitation of metric type: long is not supported yet, so casting to int
- return (int) (Math.abs(d1 - d2) / MILLISECONDS_PER_DAY);
- }
-
public static final class LastCommit {
private long date = 0;
import com.google.common.base.Optional;
import com.google.common.collect.Lists;
-import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.sonar.api.measures.CoreMetrics;
-import org.sonar.api.utils.System2;
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.metric.MetricRepositoryRule;
import static org.assertj.core.api.Assertions.assertThat;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-import static org.sonar.api.measures.CoreMetrics.DAYS_SINCE_LAST_COMMIT_KEY;
import static org.sonar.api.measures.CoreMetrics.LAST_COMMIT_DATE_KEY;
import static org.sonar.server.computation.component.Component.Type.DIRECTORY;
import static org.sonar.server.computation.component.Component.Type.FILE;
public static final int FILE_3_REF = 1_121;
public static final int DIR_1_REF = 3;
public static final int DIR_2_REF = 4;
- public static final long NOW = 1_800_000_000_000L;
@Rule
public TreeRootHolderRule treeRootHolder = new TreeRootHolderRule();
@Rule
public MetricRepositoryRule metricRepository = new MetricRepositoryRule()
- .add(CoreMetrics.LAST_COMMIT_DATE)
- .add(CoreMetrics.DAYS_SINCE_LAST_COMMIT);
+ .add(CoreMetrics.LAST_COMMIT_DATE);
@Rule
public MeasureRepositoryRule measureRepository = MeasureRepositoryRule.create(treeRootHolder, metricRepository);
- System2 system2 = mock(System2.class);
-
- @Before
- public void setUp() {
- when(system2.now()).thenReturn(NOW);
- }
-
@Test
public void aggregate_date_of_last_commit_to_directories_and_project() {
final long FILE_1_DATE = 1_100_000_000_000L;
final long FILE_3_DATE = 1_300_000_000_000L;
// simulate the output of visitFile()
- LastCommitVisitor visitor = new LastCommitVisitor(reportReader, metricRepository, measureRepository, system2) {
+ LastCommitVisitor visitor = new LastCommitVisitor(reportReader, metricRepository, measureRepository) {
@Override
public void visitFile(Component file, Path<LastCommit> path) {
long fileDate;
underTest.visit(project);
assertDate(DIR_1_REF, FILE_2_DATE);
- assertDaysSinceLastCommit(DIR_1_REF, 6944 /* number of days between FILE_2_DATE and now */);
assertDate(DIR_2_REF, FILE_3_DATE);
- assertDaysSinceLastCommit(DIR_2_REF, 5787 /* number of days between FILE_3_DATE and now */);
// module = most recent commit date of directories
assertDate(MODULE_REF, FILE_3_DATE);
- assertDaysSinceLastCommit(MODULE_REF, 5787 /* number of days between FILE_3_DATE and now */);
// project
assertDate(PROJECT_REF, FILE_3_DATE);
- assertDaysSinceLastCommit(PROJECT_REF, 5787 /* number of days between FILE_3_DATE and now */);
}
@Test
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));
- VisitorsCrawler underTest = new VisitorsCrawler(Lists.<ComponentVisitor>newArrayList(new LastCommitVisitor(reportReader, metricRepository, measureRepository, system2)));
+ VisitorsCrawler underTest = new VisitorsCrawler(Lists.<ComponentVisitor>newArrayList(new LastCommitVisitor(reportReader, metricRepository, measureRepository)));
underTest.visit(view);
// second level of sub-views
assertDate(SUBVIEW_2_REF, PROJECT_2_DATE);
- assertDaysSinceLastCommit(SUBVIEW_2_REF, 1157 /* nb of days between PROJECT_2_DATE and NOW */);
assertDate(SUBVIEW_3_REF, PROJECT_3_DATE);
- assertDaysSinceLastCommit(SUBVIEW_3_REF, 2314 /* nb of days between PROJECT_3_DATE and NOW */);
// first level of sub-views
assertDate(SUBVIEW_1_REF, PROJECT_2_DATE);
- assertDaysSinceLastCommit(SUBVIEW_1_REF, 1157 /* nb of days between PROJECT_2_DATE and NOW */);
// view
assertDate(VIEW_REF, PROJECT_2_DATE);
- assertDaysSinceLastCommit(VIEW_REF, 1157 /* nb of days between PROJECT_2_DATE and NOW */);
}
@Test
public void compute_date_of_file_from_blame_info_of_report() throws Exception {
- VisitorsCrawler underTest = new VisitorsCrawler(Lists.<ComponentVisitor>newArrayList(new LastCommitVisitor(reportReader, metricRepository, measureRepository, system2)));
+ VisitorsCrawler underTest = new VisitorsCrawler(Lists.<ComponentVisitor>newArrayList(new LastCommitVisitor(reportReader, metricRepository, measureRepository)));
BatchReport.Changesets changesets = BatchReport.Changesets.newBuilder()
.setComponentRef(FILE_1_REF)
underTest.visit(file);
assertDate(FILE_1_REF, 1_600_000_000_000L);
- assertDaysSinceLastCommit(FILE_1_REF, 2314);
}
private void assertDate(int componentRef, long expectedDate) {
assertThat(measure.get().getLongValue()).isEqualTo(expectedDate);
}
- private void assertDaysSinceLastCommit(int componentRef, int numberOfDays) {
- Optional<Measure> measure = measureRepository.getAddedRawMeasure(componentRef, DAYS_SINCE_LAST_COMMIT_KEY);
- assertThat(measure.isPresent()).isTrue();
- assertThat(measure.get().getIntValue()).isEqualTo(numberOfDays);
- }
-
/**
* 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
*/
@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, system2)));
+ VisitorsCrawler underTest = new VisitorsCrawler(Lists.<ComponentVisitor>newArrayList(new LastCommitVisitor(reportReader, metricRepository, measureRepository)));
ReportComponent file = createFileComponent(FILE_1_REF);
treeRootHolder.setRoot(file);
measureRepository.addBaseMeasure(FILE_1_REF, LAST_COMMIT_DATE_KEY, newMeasureBuilder().create(1_500_000_000L));
@Test
public void date_is_not_computed_on_file_if_blame_is_not_in_report_nor_in_previous_analysis() throws Exception {
- VisitorsCrawler underTest = new VisitorsCrawler(Lists.<ComponentVisitor>newArrayList(new LastCommitVisitor(reportReader, metricRepository, measureRepository, system2)));
+ VisitorsCrawler underTest = new VisitorsCrawler(Lists.<ComponentVisitor>newArrayList(new LastCommitVisitor(reportReader, metricRepository, measureRepository)));
ReportComponent file = createFileComponent(FILE_1_REF);
treeRootHolder.setRoot(file);
@Deprecated
public static final Metric<String> CLASS_COMPLEXITY_DISTRIBUTION = new Metric.Builder(CLASS_COMPLEXITY_DISTRIBUTION_KEY, "Classes distribution /complexity",
Metric.ValueType.DISTRIB)
- .setDescription("Classes distribution /complexity")
- .setDirection(Metric.DIRECTION_NONE)
- .setQualitative(true)
- .setDomain(DOMAIN_COMPLEXITY)
- .setHidden(true)
- .create();
+ .setDescription("Classes distribution /complexity")
+ .setDirection(Metric.DIRECTION_NONE)
+ .setQualitative(true)
+ .setDomain(DOMAIN_COMPLEXITY)
+ .setHidden(true)
+ .create();
public static final String FUNCTION_COMPLEXITY_DISTRIBUTION_KEY = "function_complexity_distribution";
public static final Metric<String> FUNCTION_COMPLEXITY_DISTRIBUTION = new Metric.Builder(FUNCTION_COMPLEXITY_DISTRIBUTION_KEY, "Functions distribution /complexity",
Metric.ValueType.DISTRIB)
- .setDescription("Functions distribution /complexity")
- .setDirection(Metric.DIRECTION_NONE)
- .setQualitative(true)
- .setDomain(DOMAIN_COMPLEXITY)
- .create();
+ .setDescription("Functions distribution /complexity")
+ .setDirection(Metric.DIRECTION_NONE)
+ .setQualitative(true)
+ .setDomain(DOMAIN_COMPLEXITY)
+ .create();
public static final String FILE_COMPLEXITY_DISTRIBUTION_KEY = "file_complexity_distribution";
public static final Metric<String> FILE_COMPLEXITY_DISTRIBUTION = new Metric.Builder(FILE_COMPLEXITY_DISTRIBUTION_KEY, "Files distribution /complexity", Metric.ValueType.DISTRIB)
*/
public static final Metric<Integer> NEW_IT_UNCOVERED_CONDITIONS = new Metric.Builder(NEW_IT_UNCOVERED_CONDITIONS_KEY, "Uncovered branches by IT on new code",
Metric.ValueType.INT)
- .setDescription("Uncovered branches by Integration Tests on new code")
- .setDirection(Metric.DIRECTION_WORST)
- .setDomain(DOMAIN_INTEGRATION_TESTS)
- .setBestValue(0.0)
- .setDeleteHistoricalData(true)
- .create();
+ .setDescription("Uncovered branches by Integration Tests on new code")
+ .setDirection(Metric.DIRECTION_WORST)
+ .setDomain(DOMAIN_INTEGRATION_TESTS)
+ .setBestValue(0.0)
+ .setDeleteHistoricalData(true)
+ .create();
/**
* @since 2.12
@Deprecated
public static final Metric<String> OVERALL_COVERAGE_LINE_HITS_DATA = new Metric.Builder(OVERALL_COVERAGE_LINE_HITS_DATA_KEY, "Overall coverage hits by line",
Metric.ValueType.DATA)
- .setDescription("Coverage hits by all tests and by line")
- .setDirection(Metric.DIRECTION_NONE)
- .setQualitative(false)
- .setDomain(DOMAIN_OVERALL_TESTS)
- .setDeleteHistoricalData(true)
- .create();
+ .setDescription("Coverage hits by all tests and by line")
+ .setDirection(Metric.DIRECTION_NONE)
+ .setQualitative(false)
+ .setDomain(DOMAIN_OVERALL_TESTS)
+ .setDeleteHistoricalData(true)
+ .create();
/**
* @since 3.3
*/
public static final Metric<Integer> NEW_OVERALL_CONDITIONS_TO_COVER = new Metric.Builder(NEW_OVERALL_CONDITIONS_TO_COVER_KEY, "Overall branches to cover on new code",
Metric.ValueType.INT)
- .setDescription("New branches to cover by all tests")
- .setDomain(DOMAIN_OVERALL_TESTS)
- .setDeleteHistoricalData(true)
- .setHidden(true)
- .create();
+ .setDescription("New branches to cover by all tests")
+ .setDomain(DOMAIN_OVERALL_TESTS)
+ .setDeleteHistoricalData(true)
+ .setHidden(true)
+ .create();
/**
* @since 3.3
*/
public static final Metric<Integer> NEW_OVERALL_UNCOVERED_CONDITIONS = new Metric.Builder(NEW_OVERALL_UNCOVERED_CONDITIONS_KEY, "Overall uncovered branches on new code",
Metric.ValueType.INT)
- .setDescription("New branches that are not covered by any test")
- .setDirection(Metric.DIRECTION_WORST)
- .setDomain(DOMAIN_OVERALL_TESTS)
- .setBestValue(0.0)
- .setDeleteHistoricalData(true)
- .create();
+ .setDescription("New branches that are not covered by any test")
+ .setDirection(Metric.DIRECTION_WORST)
+ .setDomain(DOMAIN_OVERALL_TESTS)
+ .setBestValue(0.0)
+ .setDeleteHistoricalData(true)
+ .create();
/**
* @since 3.3
*/
public static final Metric<Double> NEW_OVERALL_BRANCH_COVERAGE = new Metric.Builder(NEW_OVERALL_BRANCH_COVERAGE_KEY, "Overall condition coverage on new code",
Metric.ValueType.PERCENT)
- .setDescription("Condition coverage of new/changed code by all tests")
- .setDirection(Metric.DIRECTION_BETTER)
- .setQualitative(true)
- .setDomain(DOMAIN_OVERALL_TESTS)
- .setWorstValue(0.0)
- .setBestValue(100.0)
- .setDeleteHistoricalData(true)
- .create();
+ .setDescription("Condition coverage of new/changed code by all tests")
+ .setDirection(Metric.DIRECTION_BETTER)
+ .setQualitative(true)
+ .setDomain(DOMAIN_OVERALL_TESTS)
+ .setWorstValue(0.0)
+ .setBestValue(100.0)
+ .setDeleteHistoricalData(true)
+ .create();
/**
* @since 3.3
@Deprecated
public static final Metric<String> OVERALL_COVERED_CONDITIONS_BY_LINE = new Metric.Builder(OVERALL_COVERED_CONDITIONS_BY_LINE_KEY, "Overall covered branches by line",
Metric.ValueType.DATA)
- .setDescription("Overall covered branches by all tests and by line")
- .setDomain(DOMAIN_OVERALL_TESTS)
- .setDeleteHistoricalData(true)
- .create();
+ .setDescription("Overall covered branches by all tests and by line")
+ .setDomain(DOMAIN_OVERALL_TESTS)
+ .setDeleteHistoricalData(true)
+ .create();
// --------------------------------------------------------------------------------------------------------------------
//
@Deprecated
public static final transient Metric<String> SCM_LAST_COMMIT_DATETIMES_BY_LINE = new Metric.Builder(SCM_LAST_COMMIT_DATETIMES_BY_LINE_KEY, "Last commit dates by line",
Metric.ValueType.DATA)
- .setDomain(DOMAIN_SCM)
- .create();
+ .setDomain(DOMAIN_SCM)
+ .create();
// --------------------------------------------------------------------------------------------------------------------
//
* @since 5.2
*/
public static final Metric<Double> NEW_SQALE_DEBT_RATIO = new Metric.Builder(NEW_SQALE_DEBT_RATIO_KEY, "Technical Debt Ratio on new code", Metric.ValueType.PERCENT)
- .setDescription("Technical Debt Ratio of new/changed code.")
- .setDomain(DOMAIN_TECHNICAL_DEBT)
- .setDirection(Metric.DIRECTION_WORST)
- .setOptimizedBestValue(true)
- .setBestValue(0.0)
- .setQualitative(true)
- .create();
+ .setDescription("Technical Debt Ratio of new/changed code.")
+ .setDomain(DOMAIN_TECHNICAL_DEBT)
+ .setDirection(Metric.DIRECTION_WORST)
+ .setOptimizedBestValue(true)
+ .setBestValue(0.0)
+ .setQualitative(true)
+ .create();
// --------------------------------------------------------------------------------------------------------------------
//
.setHidden(true)
.create();
- /**
- * @since 5.2 – was computed in the dev cockpit plugin previously
- */
- public static final String DAYS_SINCE_LAST_COMMIT_KEY = "days_since_last_commit";
-
- /**
- * @since 5.2 – was computed in the dev cockpit plugin previously
- */
- public static final Metric<Integer> DAYS_SINCE_LAST_COMMIT = new Metric.Builder(DAYS_SINCE_LAST_COMMIT_KEY, "Days since last commit", Metric.ValueType.INT)
- .setDomain(CoreMetrics.DOMAIN_SCM)
- .create();
-
/**
* @since 5.2
*/