package org.sonar.server.computation.step;
import com.google.common.collect.ImmutableMap;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import javax.annotation.CheckForNull;
+import javax.annotation.Nullable;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.ibatis.session.ResultContext;
import org.apache.ibatis.session.ResultHandler;
import org.sonar.server.computation.source.SourceLinesRepository;
import org.sonar.server.computation.source.SymbolsLineReader;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
import static org.sonar.server.computation.component.ComponentVisitor.Order.PRE_ORDER;
public class PersistFileSourcesStep implements ComputationStep {
try {
ComputeFileSourceData computeFileSourceData = new ComputeFileSourceData(linesIterator, lineReaders.readers(), component.getLines());
ComputeFileSourceData.Data fileSourceData = computeFileSourceData.compute();
- persistSource(fileSourceData, file.getUuid());
+ persistSource(fileSourceData, file.getUuid(), lineReaders.getLatestChange());
} catch (Exception e) {
throw new IllegalStateException(String.format("Cannot persist sources of %s", file.getKey()), e);
} finally {
}
}
- private void persistSource(ComputeFileSourceData.Data fileSourceData, String componentUuid) {
+ private void persistSource(ComputeFileSourceData.Data fileSourceData, String componentUuid,
+ @Nullable BatchReport.Changesets.Changeset latestChange) {
DbFileSources.Data fileData = fileSourceData.getFileSourceData();
byte[] data = FileSourceDto.encodeSourceData(fileData);
.setDataHash(dataHash)
.setLineHashes(lineHashes)
.setCreatedAt(system2.now())
- .setUpdatedAt(system2.now());
+ .setUpdatedAt(system2.now())
+ .setRevision(computeRevision(latestChange));
dbClient.fileSourceDao().insert(session, dto);
session.commit();
} else {
.setDataHash(dataHash)
.setSrcHash(srcHash)
.setLineHashes(lineHashes)
+ .setRevision(computeRevision(previousDto, latestChange))
.setUpdatedAt(system2.now());
dbClient.fileSourceDao().update(previousDto);
session.commit();
}
}
+ @CheckForNull
+ private static String computeRevision(FileSourceDto previousDto, @Nullable BatchReport.Changesets.Changeset latestChange) {
+ if (latestChange == null) {
+ return previousDto.getRevision();
+ }
+ return latestChange.getRevision();
+ }
+
+ @CheckForNull
+ private static String computeRevision(@Nullable BatchReport.Changesets.Changeset latestChange) {
+ if (latestChange == null) {
+ return null;
+ }
+ return latestChange.getRevision();
+ }
+
private static class LineReaders {
private final List<LineReader> readers = new ArrayList<>();
private final List<CloseableIterator<?>> closeables = new ArrayList<>();
+ @CheckForNull
+ private final ScmLineReader scmLineReader;
LineReaders(BatchReportReader reportReader, int componentRef) {
CloseableIterator<BatchReport.Coverage> coverageIt = reportReader.readComponentCoverage(componentRef);
BatchReport.Changesets scmReport = reportReader.readChangesets(componentRef);
if (scmReport != null) {
- readers.add(new ScmLineReader(scmReport));
+ this.scmLineReader = new ScmLineReader(scmReport);
+ readers.add(scmLineReader);
+ } else {
+ this.scmLineReader = null;
}
CloseableIterator<BatchReport.SyntaxHighlighting> highlightingIt = reportReader.readComponentSyntaxHighlighting(componentRef);
reportIterator.close();
}
}
+
+ @CheckForNull
+ public BatchReport.Changesets.Changeset getLatestChange() {
+ if (scmLineReader == null) {
+ return null;
+ }
+ return scmLineReader.getLatestChange();
+ }
}
@Override
@Test
public void set_scm() {
BatchReport.Changesets scmReport = BatchReport.Changesets.newBuilder()
- .addChangeset(BatchReport.Changesets.Changeset.newBuilder()
+ .addChangeset(newChangeSetBuilder()
.setAuthor("john")
.setDate(123456789L)
.setRevision("rev-1")
@Test
public void set_only_author() {
BatchReport.Changesets scmReport = BatchReport.Changesets.newBuilder()
- .addChangeset(BatchReport.Changesets.Changeset.newBuilder()
+ .addChangeset(newChangeSetBuilder()
.setAuthor("john")
.build())
.addChangesetIndexByLine(0)
@Test
public void set_only_date() {
BatchReport.Changesets scmReport = BatchReport.Changesets.newBuilder()
- .addChangeset(BatchReport.Changesets.Changeset.newBuilder()
+ .addChangeset(newChangeSetBuilder()
.setDate(123456789L)
.build())
.addChangesetIndexByLine(0)
@Test
public void set_only_revision() {
BatchReport.Changesets scmReport = BatchReport.Changesets.newBuilder()
- .addChangeset(BatchReport.Changesets.Changeset.newBuilder()
+ .addChangeset(newChangeSetBuilder()
.setRevision("rev-1")
.build())
.addChangesetIndexByLine(0)
@Test
public void fail_when_changeset_is_empty() {
BatchReport.Changesets scmReport = BatchReport.Changesets.newBuilder()
- .addChangeset(BatchReport.Changesets.Changeset.newBuilder()
+ .addChangeset(newChangeSetBuilder()
.build())
.addChangesetIndexByLine(0)
.build();
lineScm.read(lineBuilder);
failBecauseExceptionWasNotThrown(IllegalArgumentException.class);
} catch (IllegalArgumentException e) {
- assertThat(e).hasMessage("A changeset must contains at least one of : author, revision or date");
+ assertThat(e).hasMessage("A changeset must contain at least one of : author, revision or date");
}
}
+ @Test
+ public void getLatestChange_returns_changeset_with_highest_date_of_read_lines() {
+ long refDate = 123456789L;
+ BatchReport.Changesets.Changeset changeset0 = newChangeSetBuilder().setDate(refDate - 636).build();
+ BatchReport.Changesets.Changeset changeset1 = newChangeSetBuilder().setDate(refDate + 1).build();
+ BatchReport.Changesets.Changeset changeset2 = newChangeSetBuilder().setDate(refDate + 2).build();
+ BatchReport.Changesets scmReport = setup8LinesChangeset(changeset0, changeset1, changeset2);
+
+ ScmLineReader lineScm = new ScmLineReader(scmReport);
+
+ // before any line is read, the latest change is null
+ assertThat(lineScm.getLatestChange()).isNull();
+
+ // read line 1, only one changeset => 0
+ readLineAndAssertLatestChangeDate(lineScm, 1, changeset0);
+
+ // read line 2, latest changeset is 1
+ readLineAndAssertLatestChangeDate(lineScm, 2, changeset1);
+
+ // read line 3, latest changeset is still 1
+ readLineAndAssertLatestChangeDate(lineScm, 3, changeset1);
+
+ // read line 4, latest changeset is now 2
+ readLineAndAssertLatestChangeDate(lineScm, 4, changeset2);
+
+ // read line 5 to 8, there will never be any changeset more recent than 2
+ readLineAndAssertLatestChangeDate(lineScm, 5, changeset2);
+ readLineAndAssertLatestChangeDate(lineScm, 6, changeset2);
+ readLineAndAssertLatestChangeDate(lineScm, 7, changeset2);
+ readLineAndAssertLatestChangeDate(lineScm, 8, changeset2);
+ }
+
+ @Test
+ public void getLatestChange_returns_first_changeset_when_none_have_dates() {
+ BatchReport.Changesets.Changeset changeset0 = newChangeSetBuilder().setRevision("0").build();
+ BatchReport.Changesets.Changeset changeset1 = newChangeSetBuilder().setRevision("1").build();
+ BatchReport.Changesets.Changeset changeset2 = newChangeSetBuilder().setRevision("2").build();
+ BatchReport.Changesets scmReport = setup8LinesChangeset(changeset0, changeset1, changeset2);
+
+ ScmLineReader lineScm = new ScmLineReader(scmReport);
+
+ // before any line is read, the latest change is null
+ assertThat(lineScm.getLatestChange()).isNull();
+
+ // read lines 1 to 8, no date => changeset 0
+ readLineAndAssertLatestChangeDate(lineScm, 1, changeset0);
+ readLineAndAssertLatestChangeDate(lineScm, 2, changeset0);
+ readLineAndAssertLatestChangeDate(lineScm, 3, changeset0);
+ readLineAndAssertLatestChangeDate(lineScm, 4, changeset0);
+ readLineAndAssertLatestChangeDate(lineScm, 5, changeset0);
+ readLineAndAssertLatestChangeDate(lineScm, 6, changeset0);
+ readLineAndAssertLatestChangeDate(lineScm, 7, changeset0);
+ readLineAndAssertLatestChangeDate(lineScm, 8, changeset0);
+ }
+
+ @Test
+ public void getLatestChange_returns_first_changeset_when_the_first_one_has_no_date() {
+ BatchReport.Changesets.Changeset changeset0 = newChangeSetBuilder().setRevision("0").build();
+ BatchReport.Changesets.Changeset changeset1 = newChangeSetBuilder().setRevision("1").setDate(95454154L).build();
+ BatchReport.Changesets.Changeset changeset2 = newChangeSetBuilder().setRevision("2").setDate(9654545444L).build();
+ BatchReport.Changesets scmReport = setup8LinesChangeset(changeset0, changeset1, changeset2);
+
+ ScmLineReader lineScm = new ScmLineReader(scmReport);
+
+ // before any line is read, the latest change is null
+ assertThat(lineScm.getLatestChange()).isNull();
+
+ // read lines 1 to 8, first encountered changeset has no date => changeset 0
+ readLineAndAssertLatestChangeDate(lineScm, 1, changeset0);
+ readLineAndAssertLatestChangeDate(lineScm, 2, changeset0);
+ readLineAndAssertLatestChangeDate(lineScm, 3, changeset0);
+ readLineAndAssertLatestChangeDate(lineScm, 4, changeset0);
+ readLineAndAssertLatestChangeDate(lineScm, 5, changeset0);
+ readLineAndAssertLatestChangeDate(lineScm, 6, changeset0);
+ readLineAndAssertLatestChangeDate(lineScm, 7, changeset0);
+ readLineAndAssertLatestChangeDate(lineScm, 8, changeset0);
+ }
+
+ private static BatchReport.Changesets setup8LinesChangeset(BatchReport.Changesets.Changeset changeset0,
+ BatchReport.Changesets.Changeset changeset1,
+ BatchReport.Changesets.Changeset changeset2) {
+ return BatchReport.Changesets.newBuilder()
+ .addChangeset(changeset0)
+ .addChangeset(changeset1)
+ .addChangeset(changeset2)
+ .addChangesetIndexByLine(0)
+ .addChangesetIndexByLine(1)
+ .addChangesetIndexByLine(1)
+ .addChangesetIndexByLine(2)
+ .addChangesetIndexByLine(0)
+ .addChangesetIndexByLine(1)
+ .addChangesetIndexByLine(0)
+ .addChangesetIndexByLine(0)
+ .build();
+ }
+
+ private void readLineAndAssertLatestChangeDate(ScmLineReader lineScm, int line, BatchReport.Changesets.Changeset expectedChangeset) {
+ DbFileSources.Line.Builder lineBuilder = DbFileSources.Data.newBuilder().addLinesBuilder().setLine(line);
+ lineScm.read(lineBuilder);
+ assertThat(lineScm.getLatestChange()).isSameAs(expectedChangeset);
+ }
+
+ private static BatchReport.Changesets.Changeset.Builder newChangeSetBuilder() {
+ return BatchReport.Changesets.Changeset.newBuilder();
+ }
+
}