}
if (!involvedLines.isEmpty()) {
return involvedLines.stream()
+ .filter(scmInfo::hasChangesetForLine)
.map(scmInfo::getChangesetForLine)
.max(Comparator.comparingLong(Changeset::getDate));
}
}
- Changeset latestChangeset = scmInfo.getLatestChangeset();
- if (latestChangeset != null) {
- return Optional.of(latestChangeset);
- }
-
- return Optional.empty();
+ return Optional.ofNullable(scmInfo.getLatestChangeset());
}
private static void addLines(Set<Integer> involvedLines, TextRange range) {
long lineDevCost = ratingSettings.getDevCost(file.getFileAttributes().getLanguageKey());
for (Integer nclocLineIndex : nclocLineIndexes(nclocDataMeasure)) {
- Changeset changeset = scmInfo.getChangesetForLine(nclocLineIndex);
- Period period = periodHolder.getPeriod();
- if (isLineInPeriod(changeset.getDate(), period)) {
- devCostCounter.incrementDevCost(lineDevCost);
- hasDevCost = true;
+ if (scmInfo.hasChangesetForLine(nclocLineIndex)) {
+ Changeset changeset = scmInfo.getChangesetForLine(nclocLineIndex);
+ Period period = periodHolder.getPeriod();
+ if (isLineInPeriod(changeset.getDate(), period)) {
+ devCostCounter.incrementDevCost(lineDevCost);
+ hasDevCost = true;
+ }
}
}
if (hasDevCost) {
*/
package org.sonar.server.computation.task.projectanalysis.scm;
-import com.google.common.base.Optional;
import java.util.HashMap;
-import java.util.List;
+import java.util.LinkedHashMap;
import java.util.Map;
-import java.util.Objects;
+import java.util.Optional;
import java.util.function.Function;
-import java.util.stream.StreamSupport;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import javax.annotation.concurrent.Immutable;
-import org.sonar.core.util.stream.MoreCollectors;
import org.sonar.db.protobuf.DbFileSources;
-import org.sonar.server.computation.task.projectanalysis.component.Component;
-
-import static com.google.common.base.Preconditions.checkState;
/**
* ScmInfo implementation based on the lines stored in DB
this.delegate = delegate;
}
- static Optional<ScmInfo> create(Component component, Iterable<DbFileSources.Line> lines) {
+ static Optional<ScmInfo> create(Iterable<DbFileSources.Line> lines) {
LineToChangeset lineToChangeset = new LineToChangeset();
- List<Changeset> lineChangesets = StreamSupport.stream(lines.spliterator(), false)
- .map(lineToChangeset)
- .filter(Objects::nonNull)
- .collect(MoreCollectors.toList());
- if (lineChangesets.isEmpty()) {
- return Optional.absent();
+ Map<Integer, Changeset> lineChanges = new LinkedHashMap<>();
+
+ for (DbFileSources.Line line : lines) {
+ Changeset changeset = lineToChangeset.apply(line);
+ if (changeset == null) {
+ continue;
+ }
+ lineChanges.put(line.getLine(), changeset);
}
- checkState(!lineToChangeset.isEncounteredLineWithoutScmInfo(),
- "Partial scm information stored in DB for component '%s'. Not all lines have SCM info. Can not proceed", component);
- return Optional.of(new DbScmInfo(new ScmInfoImpl(lineChangesets)));
+ if (lineChanges.isEmpty()) {
+ return Optional.empty();
+ }
+ return Optional.of(new DbScmInfo(new ScmInfoImpl(lineChanges)));
}
@Override
}
@Override
- public Iterable<Changeset> getAllChangesets() {
+ public Map<Integer, Changeset> getAllChangesets() {
return delegate.getAllChangesets();
}
/**
- * Transforms {@link org.sonar.db.protobuf.DbFileSources.Line} into {@link Changeset} and keep a flag if it encountered
- * at least one which did not have any SCM information.
+ * Transforms {@link org.sonar.db.protobuf.DbFileSources.Line} into {@link Changeset}
*/
private static class LineToChangeset implements Function<DbFileSources.Line, Changeset> {
- private boolean encounteredLineWithoutScmInfo = false;
- private final Map<String, Changeset> cache = new HashMap<>();
private final Changeset.Builder builder = Changeset.newChangesetBuilder();
+ private final HashMap<Changeset, Changeset> cache = new HashMap<>();
@Override
@Nullable
public Changeset apply(@Nonnull DbFileSources.Line input) {
- if (input.hasScmRevision() && input.hasScmDate()) {
- String revision = input.getScmRevision();
- return cache.computeIfAbsent(revision, k -> builder
- .setRevision(revision)
+ if (input.hasScmDate()) {
+ Changeset cs = builder
+ .setRevision(input.hasScmRevision() ? input.getScmRevision() : null)
.setAuthor(input.hasScmAuthor() ? input.getScmAuthor() : null)
.setDate(input.getScmDate())
- .build());
+ .build();
+ if (cache.containsKey(cs)) {
+ return cache.get(cs);
+ }
+ cache.put(cs, cs);
+ return cs;
}
- this.encounteredLineWithoutScmInfo = true;
return null;
}
-
- boolean isEncounteredLineWithoutScmInfo() {
- return encounteredLineWithoutScmInfo;
- }
}
}
*/
package org.sonar.server.computation.task.projectanalysis.scm;
-import com.google.common.base.Function;
import java.util.HashMap;
-import java.util.Iterator;
+import java.util.LinkedHashMap;
import java.util.Map;
-import java.util.NoSuchElementException;
-import javax.annotation.Nonnull;
+import java.util.function.Function;
+import java.util.stream.Collectors;
+import java.util.stream.IntStream;
import javax.annotation.concurrent.Immutable;
+import org.sonar.core.util.stream.MoreCollectors;
import org.sonar.scanner.protocol.output.ScannerReport;
-import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkState;
-import static com.google.common.collect.FluentIterable.from;
import static java.util.Objects.requireNonNull;
import static org.apache.commons.lang.StringUtils.isNotEmpty;
ReportScmInfo(ScannerReport.Changesets changesets) {
requireNonNull(changesets);
this.delegate = convertToScmInfo(changesets);
+ checkState(!delegate.getAllChangesets().isEmpty(), "Report has no changesets");
}
private static ScmInfo convertToScmInfo(ScannerReport.Changesets changesets) {
- return new ScmInfoImpl(
- from(new IntRangeIterable(changesets.getChangesetIndexByLineCount()))
- .transform(new LineIndexToChangeset(changesets)));
+ return new ScmInfoImpl(IntStream.rangeClosed(1, changesets.getChangesetIndexByLineCount())
+ .boxed()
+ .collect(Collectors.toMap(x -> x, new LineIndexToChangeset(changesets), MoreCollectors.mergeNotSupportedMerger(), LinkedHashMap::new)));
}
@Override
}
@Override
- public Iterable<Changeset> getAllChangesets() {
+ public Map<Integer, Changeset> getAllChangesets() {
return this.delegate.getAllChangesets();
}
}
@Override
- @Nonnull
- public Changeset apply(@Nonnull Integer lineNumber) {
+ public Changeset apply(Integer lineNumber) {
int changesetIndex = changesets.getChangesetIndexByLine(lineNumber - 1);
- Changeset changeset = changesetCache.get(changesetIndex);
- if (changeset != null) {
- return changeset;
- }
- Changeset res = convert(changesets.getChangeset(changesetIndex), lineNumber);
- changesetCache.put(changesetIndex, res);
- return res;
+ return changesetCache.computeIfAbsent(changesetIndex, idx -> convert(changesets.getChangeset(changesetIndex), lineNumber));
}
private Changeset convert(ScannerReport.Changesets.Changeset changeset, int line) {
.build();
}
}
-
- /**
- * A simple Iterable which generate integer from 0 (included) to a specific value (excluded).
- */
- private static final class IntRangeIterable implements Iterable<Integer> {
- private final int max;
-
- private IntRangeIterable(int max) {
- checkArgument(max >= 0, "Max value must be >= 0");
- this.max = max;
- }
-
- @Override
- public Iterator<Integer> iterator() {
- return new IntRangeIterator(max);
- }
- }
-
- private static class IntRangeIterator implements Iterator<Integer> {
- private final int max;
-
- private int current = 0;
-
- public IntRangeIterator(int max) {
- this.max = max;
- }
-
- @Override
- public boolean hasNext() {
- return current < max;
- }
-
- @Override
- public Integer next() {
- if (!hasNext()) {
- throw new NoSuchElementException();
- }
- current++;
- return current;
- }
-
- @Override
- public void remove() {
- throw new UnsupportedOperationException("Remove cannot be called");
- }
- }
}
*/
package org.sonar.server.computation.task.projectanalysis.scm;
+import java.util.Map;
+
/**
* Represents the Scm information for a specific file.
*/
/**
* Get ChangeSet of the file for given line
*
- * @throws IllegalArgumentException if there is no Changeset for the specified line, ie. the line number in invalid (either less than 1 or > linecount of the file)
+ * @throws IllegalArgumentException if there is no Changeset for the specified line
*/
Changeset getChangesetForLine(int lineNumber);
boolean hasChangesetForLine(int lineNumber);
/**
- * Return all ChangeSets, in order, for all lines of the file
+ * Return all ChangeSets, in order, for all lines that have changesets.
*/
- Iterable<Changeset> getAllChangesets();
+ Map<Integer, Changeset> getAllChangesets();
}
if (dto == null || !isDtoValid(file, dto)) {
return NoScmInfo.INSTANCE;
}
- return DbScmInfo.create(file, dto.getSourceData().getLinesList()).or(NoScmInfo.INSTANCE);
+ return DbScmInfo.create(dto.getSourceData().getLinesList()).orElse(NoScmInfo.INSTANCE);
}
}
*/
package org.sonar.server.computation.task.projectanalysis.scm;
-import com.google.common.base.Predicate;
-import java.util.Arrays;
+import java.util.Comparator;
+import java.util.Map;
+import java.util.stream.Collectors;
import javax.annotation.CheckForNull;
-import javax.annotation.Nullable;
import javax.annotation.concurrent.Immutable;
-import static com.google.common.base.Preconditions.checkArgument;
-import static com.google.common.base.Preconditions.checkState;
-import static com.google.common.collect.FluentIterable.from;
-import static com.google.common.collect.Iterables.isEmpty;
-import static java.util.Arrays.asList;
-
@Immutable
public class ScmInfoImpl implements ScmInfo {
@CheckForNull
private final Changeset latestChangeset;
- private final Changeset[] lineChangesets;
+ private final Map<Integer, Changeset> lineChangesets;
- public ScmInfoImpl(Iterable<Changeset> lineChangesets) {
- checkState(!isEmpty(lineChangesets), "A ScmInfo must have at least one Changeset and does not support any null one");
- this.lineChangesets = from(lineChangesets)
- .filter(CheckNotNull.INSTANCE)
- .toArray(Changeset.class);
+ public ScmInfoImpl(Map<Integer, Changeset> lineChangesets) {
+ this.lineChangesets = lineChangesets;
this.latestChangeset = computeLatestChangeset(lineChangesets);
}
- private static Changeset computeLatestChangeset(Iterable<Changeset> lineChangesets) {
- Changeset latestChangeset = null;
- for (Changeset lineChangeset : lineChangesets) {
- if (latestChangeset == null || lineChangeset.getDate() > latestChangeset.getDate()) {
- latestChangeset = lineChangeset;
- }
- }
- return latestChangeset;
+ private static Changeset computeLatestChangeset(Map<Integer, Changeset> lineChangesets) {
+ return lineChangesets.values().stream()
+ .collect(Collectors.maxBy(Comparator.comparing(Changeset::getDate)))
+ .orElse(null);
}
@Override
@Override
public Changeset getChangesetForLine(int lineNumber) {
- checkArgument(lineNumber > 0 && lineNumber <= lineChangesets.length, "There's no changeset on line %s", lineNumber);
- return lineChangesets[lineNumber - 1];
+ Changeset changeset = lineChangesets.get(lineNumber);
+ if (changeset != null) {
+ return changeset;
+ }
+ throw new IllegalArgumentException("Line " + lineNumber + " doesn't have a changeset");
}
@Override
public boolean hasChangesetForLine(int lineNumber) {
- return lineNumber <= lineChangesets.length;
+ return lineChangesets.containsKey(lineNumber);
}
@Override
- public Iterable<Changeset> getAllChangesets() {
- return asList(lineChangesets);
+ public Map<Integer, Changeset> getAllChangesets() {
+ return lineChangesets;
}
@Override
public String toString() {
return "ScmInfoImpl{" +
"latestChangeset=" + latestChangeset +
- ", lineChangesets=" + Arrays.toString(lineChangesets) +
+ ", lineChangesets=" + lineChangesets +
'}';
}
-
- private enum CheckNotNull implements Predicate<Changeset> {
- INSTANCE;
-
- @Override
- public boolean apply(@Nullable Changeset input) {
- checkState(input != null, "Null changeset are not allowed");
- return true;
- }
- }
}
@Override
public void read(DbFileSources.Line.Builder lineBuilder) {
- Changeset changeset = scmReport.getChangesetForLine(lineBuilder.getLine());
- String author = changeset.getAuthor();
- if (author != null) {
- lineBuilder.setScmAuthor(author);
- }
- String revision = changeset.getRevision();
- if (revision != null) {
- lineBuilder.setScmRevision(revision);
- }
- lineBuilder.setScmDate(changeset.getDate());
- updateLatestChange(changeset);
+ if (scmReport.hasChangesetForLine(lineBuilder.getLine())) {
+ Changeset changeset = scmReport.getChangesetForLine(lineBuilder.getLine());
+ String author = changeset.getAuthor();
+ if (author != null) {
+ lineBuilder.setScmAuthor(author);
+ }
+ String revision = changeset.getRevision();
+ if (revision != null) {
+ lineBuilder.setScmRevision(revision);
+ }
+ lineBuilder.setScmDate(changeset.getDate());
+ updateLatestChange(changeset);
- if (revision != null) {
- updateLatestChangeWithRevision(changeset);
+ if (revision != null) {
+ updateLatestChangeWithRevision(changeset);
+ }
}
}
import org.sonar.server.computation.task.projectanalysis.component.Component;
import org.sonar.server.computation.task.projectanalysis.component.PathAwareCrawler;
import org.sonar.server.computation.task.projectanalysis.component.TreeRootHolder;
+import org.sonar.server.computation.task.projectanalysis.formula.Counter;
import org.sonar.server.computation.task.projectanalysis.formula.CounterInitializationContext;
import org.sonar.server.computation.task.projectanalysis.formula.CreateMeasureContext;
import org.sonar.server.computation.task.projectanalysis.formula.Formula;
}
}
- public static final class NewCoverageCounter implements org.sonar.server.computation.task.projectanalysis.formula.Counter<NewCoverageCounter> {
+ public static final class NewCoverageCounter implements Counter<NewCoverageCounter> {
private final IntValue newLines = new IntValue();
private final IntValue newCoveredLines = new IntValue();
private final IntValue newConditions = new IntValue();
int hits = entry.getValue();
int conditions = (Integer) ObjectUtils.defaultIfNull(conditionsByLine.get(lineId), 0);
int coveredConditions = (Integer) ObjectUtils.defaultIfNull(coveredConditionsByLine.get(lineId), 0);
- long date = componentScm.getChangesetForLine(lineId).getDate();
- analyze(context.getPeriod(), date, hits, conditions, coveredConditions);
+ if (componentScm.hasChangesetForLine(lineId)) {
+ analyze(context.getPeriod(), componentScm.getChangesetForLine(lineId).getDate(), hits, conditions, coveredConditions);
+ }
}
}
return Collections.emptyMap();
}
- void analyze(Period period, @Nullable Long lineDate, int hits, int conditions, int coveredConditions) {
- if (lineDate == null) {
- return;
- }
+ void analyze(Period period, long lineDate, int hits, int conditions, int coveredConditions) {
if (isLineInPeriod(lineDate, period)) {
incrementLines(hits);
incrementConditions(conditions, coveredConditions);
import com.google.common.base.Optional;
import com.google.common.collect.ImmutableList;
-import com.google.common.collect.Iterables;
import java.util.HashSet;
import java.util.Set;
import java.util.stream.IntStream;
-import java.util.stream.StreamSupport;
import org.sonar.server.computation.task.projectanalysis.component.Component;
import org.sonar.server.computation.task.projectanalysis.component.PathAwareCrawler;
import org.sonar.server.computation.task.projectanalysis.component.TreeRootHolder;
private final NewDuplicationFormula duplicationFormula;
public NewSizeMeasuresStep(TreeRootHolder treeRootHolder, PeriodHolder periodHolder, MetricRepository metricRepository, MeasureRepository measureRepository,
- ScmInfoRepository scmInfoRepository, DuplicationRepository duplicationRepository) {
+ ScmInfoRepository scmInfoRepository, DuplicationRepository duplicationRepository) {
this.treeRootHolder = treeRootHolder;
this.periodHolder = periodHolder;
this.metricRepository = metricRepository;
}
private void initNewLines(ScmInfo scmInfo, Period period) {
- StreamSupport.stream(scmInfo.getAllChangesets().spliterator(), false)
+ scmInfo.getAllChangesets().values().stream()
.filter(changeset -> isLineInPeriod(changeset, period))
.forEach(changeset -> newLines.increment(1));
}
private DuplicationCounters(ScmInfo scmInfo, Period period) {
this.scmInfo = scmInfo;
this.period = period;
- this.lineCounts = new HashSet<>(Iterables.size(scmInfo.getAllChangesets()));
+ this.lineCounts = new HashSet<>();
}
void addBlock(TextBlock textBlock) {
private void withScmAt(int line, long blame) {
createMockScmInfo();
Changeset changeset = Changeset.newChangesetBuilder().setDate(blame).setRevision("1").build();
+ when(scmInfo.hasChangesetForLine(line)).thenReturn(true);
when(scmInfo.getChangesetForLine(line)).thenReturn(changeset);
}
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.sonar.db.protobuf.DbFileSources;
-import org.sonar.server.computation.task.projectanalysis.component.Component;
import static org.assertj.core.api.Assertions.assertThat;
-import static org.assertj.guava.api.Assertions.assertThat;
-import static org.sonar.server.computation.task.projectanalysis.component.ReportComponent.builder;
import static org.sonar.server.source.index.FileSourceTesting.newFakeData;
public class DbScmInfoTest {
@Rule
public ExpectedException thrown = ExpectedException.none();
- static final int FILE_REF = 1;
- static final Component FILE = builder(Component.Type.FILE, FILE_REF).setKey("FILE_KEY").setUuid("FILE_UUID").build();
-
@Test
public void create_scm_info_with_some_changesets() throws Exception {
- ScmInfo scmInfo = DbScmInfo.create(FILE, newFakeData(10).build().getLinesList()).get();
+ ScmInfo scmInfo = DbScmInfo.create(newFakeData(10).build().getLinesList()).get();
assertThat(scmInfo.getAllChangesets()).hasSize(10);
}
addLine(fileDataBuilder, 4, "john", 123456789L, "rev-1");
fileDataBuilder.build();
- ScmInfo scmInfo = DbScmInfo.create(FILE, fileDataBuilder.getLinesList()).get();
+ ScmInfo scmInfo = DbScmInfo.create(fileDataBuilder.getLinesList()).get();
assertThat(scmInfo.getAllChangesets()).hasSize(4);
}
@Test
- public void return_same_changeset_objects_for_lines_with_same_revision() {
+ public void return_same_changeset_objects_for_lines_with_same_fields() throws Exception {
DbFileSources.Data.Builder fileDataBuilder = DbFileSources.Data.newBuilder();
fileDataBuilder.addLinesBuilder().setScmRevision("rev").setScmDate(65L).setLine(1);
fileDataBuilder.addLinesBuilder().setScmRevision("rev2").setScmDate(6541L).setLine(2);
fileDataBuilder.addLinesBuilder().setScmRevision("rev1").setScmDate(6541L).setLine(3);
- fileDataBuilder.addLinesBuilder().setScmRevision("rev").setScmDate(6542L).setLine(4);
+ fileDataBuilder.addLinesBuilder().setScmRevision("rev").setScmDate(65L).setLine(4);
- ScmInfo scmInfo = DbScmInfo.create(FILE, fileDataBuilder.getLinesList()).get();
+ ScmInfo scmInfo = DbScmInfo.create(fileDataBuilder.getLinesList()).get();
assertThat(scmInfo.getAllChangesets()).hasSize(4);
addLine(fileDataBuilder, 3, "john", 123456789L, "rev-1");
fileDataBuilder.build();
- ScmInfo scmInfo = DbScmInfo.create(FILE, fileDataBuilder.getLinesList()).get();
+ ScmInfo scmInfo = DbScmInfo.create(fileDataBuilder.getLinesList()).get();
Changeset latestChangeset = scmInfo.getLatestChangeset();
assertThat(latestChangeset.getAuthor()).isEqualTo("henry");
DbFileSources.Data.Builder fileDataBuilder = DbFileSources.Data.newBuilder();
fileDataBuilder.addLinesBuilder().setLine(1);
- assertThat(DbScmInfo.create(FILE, fileDataBuilder.getLinesList())).isAbsent();
- }
-
- @Test
- public void return_absent_dsm_info_when_changeset_line_has_both_revision_and_date() {
- DbFileSources.Data.Builder fileDataBuilder = DbFileSources.Data.newBuilder();
- fileDataBuilder.addLinesBuilder().setLine(1);
- fileDataBuilder.addLinesBuilder().setScmDate(6541L).setLine(2);
- fileDataBuilder.addLinesBuilder().setScmRevision("rev").setLine(3);
- fileDataBuilder.addLinesBuilder().setScmAuthor("author").setLine(4);
-
- assertThat(DbScmInfo.create(FILE, fileDataBuilder.getLinesList())).isAbsent();
+ assertThat(DbScmInfo.create(fileDataBuilder.getLinesList())).isNotPresent();
}
@Test
- public void fail_with_ISE_when_changeset_has_no_field() {
- thrown.expect(IllegalStateException.class);
- thrown.expectMessage("Partial scm information stored in DB for component 'ReportComponent{ref=1, key='FILE_KEY', type=FILE}'. " +
- "Not all lines have SCM info. Can not proceed");
-
+ public void should_support_some_lines_not_having_scm_info() throws Exception {
DbFileSources.Data.Builder fileDataBuilder = DbFileSources.Data.newBuilder();
fileDataBuilder.addLinesBuilder().setScmRevision("rev").setScmDate(543L).setLine(1);
fileDataBuilder.addLinesBuilder().setLine(2);
fileDataBuilder.build();
- DbScmInfo.create(FILE, fileDataBuilder.getLinesList()).get().getAllChangesets();
+ assertThat(DbScmInfo.create(fileDataBuilder.getLinesList()).get().getAllChangesets()).hasSize(1);
}
@Test
- public void fail_with_ISE_when_changeset_has_only_revision_field() {
- thrown.expect(IllegalStateException.class);
- thrown.expectMessage("Partial scm information stored in DB for component 'ReportComponent{ref=1, key='FILE_KEY', type=FILE}'. " +
- "Not all lines have SCM info. Can not proceed");
-
+ public void filter_out_entries_without_date() throws Exception {
DbFileSources.Data.Builder fileDataBuilder = DbFileSources.Data.newBuilder();
fileDataBuilder.addLinesBuilder().setScmRevision("rev").setScmDate(555L).setLine(1);
fileDataBuilder.addLinesBuilder().setScmRevision("rev-1").setLine(2);
fileDataBuilder.build();
- DbScmInfo.create(FILE, fileDataBuilder.getLinesList()).get().getAllChangesets();
+ assertThat(DbScmInfo.create(fileDataBuilder.getLinesList()).get().getAllChangesets()).hasSize(1);
+ assertThat(DbScmInfo.create(fileDataBuilder.getLinesList()).get().getChangesetForLine(1).getRevision()).isEqualTo("rev");
}
@Test
- public void fail_with_ISE_when_changeset_has_only_author_field() {
- thrown.expect(IllegalStateException.class);
- thrown.expectMessage("Partial scm information stored in DB for component 'ReportComponent{ref=1, key='FILE_KEY', type=FILE}'. " +
- "Not all lines have SCM info. Can not proceed");
-
+ public void should_support_having_no_author() throws Exception {
DbFileSources.Data.Builder fileDataBuilder = DbFileSources.Data.newBuilder();
+ // gets filtered out
fileDataBuilder.addLinesBuilder().setScmAuthor("John").setLine(1);
fileDataBuilder.addLinesBuilder().setScmRevision("rev").setScmDate(555L).setLine(2);
fileDataBuilder.build();
- DbScmInfo.create(FILE, fileDataBuilder.getLinesList()).get().getAllChangesets();
+ assertThat(DbScmInfo.create(fileDataBuilder.getLinesList()).get().getAllChangesets()).hasSize(1);
+ assertThat(DbScmInfo.create(fileDataBuilder.getLinesList()).get().getChangesetForLine(2).getAuthor()).isNull();
}
private static void addLine(DbFileSources.Data.Builder dataBuilder, Integer line, String author, Long date, String revision) {
*/
package org.sonar.server.computation.task.projectanalysis.scm;
-import com.google.common.collect.Lists;
+import com.google.common.collect.ImmutableMap;
+import java.util.Collections;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
-import static com.google.common.collect.Lists.newArrayList;
import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.entry;
public class ScmInfoImplTest {
public void get_all_changesets() {
ScmInfo scmInfo = createScmInfoWithTwoChangestOnFourLines();
- assertThat(scmInfo.getAllChangesets()).containsOnly(CHANGESET_1, CHANGESET_2, CHANGESET_1, CHANGESET_1);
+ assertThat(scmInfo.getAllChangesets()).containsOnly(entry(1, CHANGESET_1), entry(2, CHANGESET_2), entry(3, CHANGESET_1), entry(4, CHANGESET_1));
}
@Test
thrown.expect(IllegalStateException.class);
thrown.expectMessage("A ScmInfo must have at least one Changeset and does not support any null one");
- new ScmInfoImpl(Lists.newArrayList());
+ new ScmInfoImpl(Collections.emptyMap());
}
@Test
.setRevision("rev-2")
.build();
- ScmInfo scmInfo = new ScmInfoImpl(newArrayList(changeset1, changeset2, changeset1, changeset1));
+ ScmInfo scmInfo = new ScmInfoImpl(ImmutableMap.of(1, changeset1, 2, changeset2, 3, changeset1, 4, changeset1));
return scmInfo;
}
}
package org.sonar.server.computation.task.projectanalysis.scm;
import com.google.common.base.Optional;
-import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
+import java.util.stream.Collectors;
+import java.util.stream.IntStream;
import org.junit.rules.ExternalResource;
import org.sonar.server.computation.task.projectanalysis.component.Component;
}
public ScmInfoRepositoryRule setScmInfo(int fileRef, Changeset... changesetList) {
- scmInfoByFileRef.put(fileRef, new ScmInfoImpl(Arrays.asList(changesetList)));
+ Map<Integer, Changeset> changeset = IntStream.rangeClosed(1, changesetList.length).boxed().collect(Collectors.toMap(x -> x, x -> changesetList[x-1]));
+ scmInfoByFileRef.put(fileRef, new ScmInfoImpl(changeset));
return this;
}
}
*/
package org.sonar.server.computation.task.projectanalysis.source;
-import com.google.common.collect.ImmutableList;
-import java.util.List;
+import com.google.common.collect.ImmutableMap;
+import java.util.Collections;
+import java.util.Map;
import org.junit.Test;
import org.sonar.db.protobuf.DbFileSources;
import org.sonar.server.computation.task.projectanalysis.scm.Changeset;
import org.sonar.server.computation.task.projectanalysis.scm.ScmInfo;
import org.sonar.server.computation.task.projectanalysis.scm.ScmInfoImpl;
-import static com.google.common.collect.Lists.newArrayList;
import static org.assertj.core.api.Assertions.assertThat;
public class ScmLineReaderTest {
@Test
public void set_scm() {
- ScmInfo scmInfo = new ScmInfoImpl(newArrayList(
+ ScmInfo scmInfo = new ScmInfoImpl(Collections.singletonMap(1,
Changeset.newChangesetBuilder()
.setAuthor("john")
.setDate(123_456_789L)
.setRevision("rev-1")
- .build()
- ));
+ .build()));
ScmLineReader lineScm = new ScmLineReader(scmInfo);
@Test
public void set_scm_with_minim_fields() {
- ScmInfo scmInfo = new ScmInfoImpl(newArrayList(
+ ScmInfo scmInfo = new ScmInfoImpl(Collections.singletonMap(1,
Changeset.newChangesetBuilder()
.setDate(123_456_789L)
.setRevision("rev-1")
- .build()
- ));
+ .build()));
ScmLineReader lineScm = new ScmLineReader(scmInfo);
readLineAndAssertLatestChangeDate(lineScm, 8, changeset2);
}
- private static List<Changeset> setup8LinesChangeset(Changeset changeset0, Changeset changeset1, Changeset changeset2) {
- return ImmutableList.of(changeset0, changeset1, changeset1, changeset2, changeset0, changeset1, changeset0, changeset0);
+ private static Map<Integer, Changeset> setup8LinesChangeset(Changeset changeset0, Changeset changeset1, Changeset changeset2) {
+ return ImmutableMap.<Integer, Changeset>builder()
+ .put(1, changeset0)
+ .put(2, changeset1)
+ .put(3, changeset1)
+ .put(4, changeset2)
+ .put(5, changeset0)
+ .put(6, changeset1)
+ .put(7, changeset0)
+ .put(8, changeset0).build();
}
private void readLineAndAssertLatestChangeDate(ScmLineReader lineScm, int line, Changeset expectedChangeset) {
assertThat(data.getLines(0).getScmRevision()).isEqualTo("rev-1");
}
+ @Test
+ public void persist_scm_some_lines() {
+ initBasicReport(3);
+ scmInfoRepository.setScmInfo(FILE1_REF, Changeset.newChangesetBuilder()
+ .setAuthor("john")
+ .setDate(123456789L)
+ .setRevision("rev-1")
+ .build());
+
+ underTest.execute();
+
+ assertThat(dbTester.countRowsOfTable("file_sources")).isEqualTo(1);
+ FileSourceDto fileSourceDto = dbClient.fileSourceDao().selectSourceByFileUuid(session, FILE1_UUID);
+
+ assertThat(fileSourceDto.getRevision()).isEqualTo("rev-1");
+
+ DbFileSources.Data data = fileSourceDto.getSourceData();
+
+ assertThat(data.getLinesList()).hasSize(3);
+
+ assertThat(data.getLines(0).getScmAuthor()).isEqualTo("john");
+ assertThat(data.getLines(0).getScmDate()).isEqualTo(123456789L);
+ assertThat(data.getLines(0).getScmRevision()).isEqualTo("rev-1");
+
+ assertThat(data.getLines(1).getScmAuthor()).isEmpty();
+ assertThat(data.getLines(1).getScmDate()).isEqualTo(0);
+ assertThat(data.getLines(1).getScmRevision()).isEmpty();
+
+ assertThat(data.getLines(2).getScmAuthor()).isEmpty();
+ assertThat(data.getLines(2).getScmDate()).isEqualTo(0);
+ assertThat(data.getLines(2).getScmRevision()).isEmpty();
+ }
+
@Test
public void persist_highlighting() {
initBasicReport(1);
joiner::join);
}
- private static <R> BinaryOperator<R> mergeNotSupportedMerger() {
+ public static <R> BinaryOperator<R> mergeNotSupportedMerger() {
return (m1, m2) -> {
throw new IllegalStateException("Parallel processing is not supported");
};