mirror of
https://github.com/SonarSource/sonarqube.git
synced 2024-07-29 08:17:28 +02:00
SONAR-5815 Store last update time on source data
This commit is contained in:
parent
19a6905ce6
commit
89eede7717
@ -20,12 +20,15 @@
|
||||
package org.sonar.batch.protocol.input;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
|
||||
import javax.annotation.CheckForNull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
@ -40,6 +43,7 @@ public class ProjectReferentials {
|
||||
private Collection<ActiveRule> activeRules = new ArrayList<ActiveRule>();
|
||||
private Map<String, Map<String, String>> settingsByModule = new HashMap<String, Map<String, String>>();
|
||||
private Map<String, Map<String, FileData>> fileDataByModuleAndPath = new HashMap<String, Map<String, FileData>>();
|
||||
private Date lastAnalysisDate;
|
||||
|
||||
public Map<String, String> settings(String projectKey) {
|
||||
return settingsByModule.containsKey(projectKey) ? settingsByModule.get(projectKey) : Collections.<String, String>emptyMap();
|
||||
@ -100,12 +104,23 @@ public class ProjectReferentials {
|
||||
this.timestamp = timestamp;
|
||||
}
|
||||
|
||||
@CheckForNull
|
||||
public Date lastAnalysisDate() {
|
||||
return lastAnalysisDate;
|
||||
}
|
||||
|
||||
public void setLastAnalysisDate(@Nullable Date lastAnalysisDate) {
|
||||
this.lastAnalysisDate = lastAnalysisDate;
|
||||
}
|
||||
|
||||
public String toJson() {
|
||||
return new Gson().toJson(this);
|
||||
Gson gson = new GsonBuilder().setDateFormat("yyyy-MM-dd'T'HH:mm:ssZ").create();
|
||||
return gson.toJson(this);
|
||||
}
|
||||
|
||||
public static ProjectReferentials fromJson(String json) {
|
||||
return new Gson().fromJson(json, ProjectReferentials.class);
|
||||
Gson gson = new GsonBuilder().setDateFormat("yyyy-MM-dd'T'HH:mm:ssZ").create();
|
||||
return gson.fromJson(json, ProjectReferentials.class);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -48,6 +48,7 @@ public class ProjectReferentialsTest {
|
||||
ActiveRule activeRule = new ActiveRule("repo", "rule", "Rule", "MAJOR", "rule", "java");
|
||||
activeRule.addParam("param1", "value1");
|
||||
ref.addActiveRule(activeRule);
|
||||
ref.setLastAnalysisDate(new SimpleDateFormat("dd/MM/yyyy").parse("31/10/2014"));
|
||||
ref.setTimestamp(10);
|
||||
ref.addFileData("foo", "src/main/java/Foo.java", new FileData("xyz", "1=12345,2=3456", "1=345,2=345", "1=henryju,2=gaudin"));
|
||||
|
||||
@ -55,10 +56,11 @@ public class ProjectReferentialsTest {
|
||||
JSONAssert
|
||||
.assertEquals(
|
||||
"{timestamp:10,"
|
||||
+ "qprofilesByLanguage:{java:{key:\"squid-java\",name:Java,language:java,rulesUpdatedAt:\"Mar 14, 1984 12:00:00 AM\"}},"
|
||||
+ "qprofilesByLanguage:{java:{key:\"squid-java\",name:Java,language:java,rulesUpdatedAt:\"1984-03-14T00:00:00+0100\"}},"
|
||||
+ "activeRules:[{repositoryKey:repo,ruleKey:rule,name:Rule,severity:MAJOR,internalKey:rule,language:java,params:{param1:value1}}],"
|
||||
+ "settingsByModule:{foo:{prop1:value1,prop2:value2,prop:value}},"
|
||||
+ "fileDataByModuleAndPath:{foo:{\"src/main/java/Foo.java\":{hash:xyz,scmLastCommitDatetimesByLine:\"1\u003d12345,2\u003d3456\",scmRevisionsByLine:\"1\u003d345,2\u003d345\",scmAuthorsByLine:\"1\u003dhenryju,2\u003dgaudin\"}}}}",
|
||||
+ "fileDataByModuleAndPath:{foo:{\"src/main/java/Foo.java\":{hash:xyz,scmLastCommitDatetimesByLine:\"1\u003d12345,2\u003d3456\",scmRevisionsByLine:\"1\u003d345,2\u003d345\",scmAuthorsByLine:\"1\u003dhenryju,2\u003dgaudin\"}}},"
|
||||
+ "lastAnalysisDate:\"2014-10-31T00:00:00+0100\"}",
|
||||
ref.toJson(), true);
|
||||
}
|
||||
|
||||
@ -66,10 +68,11 @@ public class ProjectReferentialsTest {
|
||||
public void testFromJson() throws JSONException, ParseException {
|
||||
ProjectReferentials ref = ProjectReferentials
|
||||
.fromJson("{timestamp:1,"
|
||||
+ "qprofilesByLanguage:{java:{key:\"squid-java\",name:Java,language:java,rulesUpdatedAt:\"Mar 14, 1984 12:00:00 AM\"}},"
|
||||
+ "qprofilesByLanguage:{java:{key:\"squid-java\",name:Java,language:java,rulesUpdatedAt:\"1984-03-14T00:00:00+0100\"}},"
|
||||
+ "activeRules:[{repositoryKey:repo,ruleKey:rule,name:Rule,severity:MAJOR,internalKey:rule1,language:java,params:{param1:value1}}],"
|
||||
+ "settingsByModule:{foo:{prop:value}},"
|
||||
+ "fileDataByModuleAndPath:{foo:{\"src/main/java/Foo.java\":{hash:xyz,scmLastCommitDatetimesByLine:\"1\u003d12345,2\u003d3456\",scmRevisionsByLine:\"1\u003d345,2\u003d345\",scmAuthorsByLine:\"1\u003dhenryju,2\u003dgaudin\"}}}}");
|
||||
+ "fileDataByModuleAndPath:{foo:{\"src/main/java/Foo.java\":{hash:xyz,scmLastCommitDatetimesByLine:\"1\u003d12345,2\u003d3456\",scmRevisionsByLine:\"1\u003d345,2\u003d345\",scmAuthorsByLine:\"1\u003dhenryju,2\u003dgaudin\"}}},"
|
||||
+ "lastAnalysisDate:\"2014-10-31T00:00:00+0100\"}");
|
||||
|
||||
assertThat(ref.timestamp()).isEqualTo(1);
|
||||
|
||||
@ -92,5 +95,7 @@ public class ProjectReferentialsTest {
|
||||
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()).isEqualTo(new SimpleDateFormat("dd/MM/yyyy").parse("31/10/2014"));
|
||||
}
|
||||
}
|
||||
|
@ -10,9 +10,9 @@
|
||||
<entry key="Post-Jobs">30</entry>
|
||||
<entry key="FakeSensor">10</entry>
|
||||
<entry key="Maven">4</entry>
|
||||
<entry key="Free memory">9</entry>
|
||||
<entry key="Persisters">40</entry>
|
||||
<entry key="Decorators">30</entry>
|
||||
<entry key="FakeInitializer">7</entry>
|
||||
<entry key="Persisters">40</entry>
|
||||
<entry key="Free memory">9</entry>
|
||||
<entry key="Sensors">10</entry>
|
||||
<entry key="FakeInitializer">7</entry>
|
||||
</properties>
|
||||
|
@ -10,9 +10,9 @@
|
||||
<entry key="Post-Jobs">90</entry>
|
||||
<entry key="FakeSensor">30</entry>
|
||||
<entry key="Maven">12</entry>
|
||||
<entry key="Free memory">27</entry>
|
||||
<entry key="Persisters">120</entry>
|
||||
<entry key="Decorators">90</entry>
|
||||
<entry key="FakeInitializer">21</entry>
|
||||
<entry key="Persisters">120</entry>
|
||||
<entry key="Free memory">27</entry>
|
||||
<entry key="Sensors">30</entry>
|
||||
<entry key="FakeInitializer">21</entry>
|
||||
</properties>
|
||||
|
@ -474,14 +474,6 @@ public class DefaultIndex extends SonarIndex {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSource(Resource reference, String source) {
|
||||
Bucket bucket = getBucket(reference);
|
||||
if (bucket != null) {
|
||||
persistence.setSource(reference, source);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSource(Resource resource) {
|
||||
return persistence.getSource(resource);
|
||||
|
@ -51,7 +51,6 @@ public final class DefaultPersistenceManager implements PersistenceManager {
|
||||
@Override
|
||||
public void clear() {
|
||||
resourcePersister.clear();
|
||||
sourcePersister.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -67,11 +66,6 @@ public final class DefaultPersistenceManager implements PersistenceManager {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSource(Resource file, String source) {
|
||||
sourcePersister.saveSource(file, source);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSource(Resource resource) {
|
||||
return sourcePersister.getSource(resource);
|
||||
|
@ -37,8 +37,6 @@ public interface PersistenceManager {
|
||||
|
||||
Snapshot saveResource(Project project, Resource resource, @Nullable Resource parent);
|
||||
|
||||
void setSource(Resource file, String source);
|
||||
|
||||
String getSource(Resource resource);
|
||||
|
||||
void saveDependency(Project project, Dependency dependency, Dependency parentDependency);
|
||||
|
@ -19,20 +19,17 @@
|
||||
*/
|
||||
package org.sonar.batch.index;
|
||||
|
||||
import com.google.common.collect.Sets;
|
||||
import org.sonar.api.database.model.Snapshot;
|
||||
import org.sonar.api.resources.DuplicatedSourceException;
|
||||
import org.sonar.api.resources.Resource;
|
||||
import org.sonar.core.source.db.SnapshotSourceDao;
|
||||
import org.sonar.core.source.db.SnapshotSourceDto;
|
||||
|
||||
import javax.annotation.CheckForNull;
|
||||
|
||||
import java.util.Set;
|
||||
import java.util.Date;
|
||||
|
||||
public final class SourcePersister {
|
||||
public class SourcePersister {
|
||||
|
||||
private Set<Integer> savedSnapshotIds = Sets.newHashSet();
|
||||
private ResourcePersister resourcePersister;
|
||||
private final SnapshotSourceDao sourceDao;
|
||||
|
||||
@ -41,16 +38,13 @@ public final class SourcePersister {
|
||||
this.sourceDao = sourceDao;
|
||||
}
|
||||
|
||||
public void saveSource(Resource resource, String source) {
|
||||
public void saveSource(Resource resource, String source, Date updatedAt) {
|
||||
Snapshot snapshot = resourcePersister.getSnapshotOrFail(resource);
|
||||
if (isCached(snapshot)) {
|
||||
throw new DuplicatedSourceException(resource);
|
||||
}
|
||||
SnapshotSourceDto dto = new SnapshotSourceDto();
|
||||
dto.setSnapshotId(snapshot.getId().longValue());
|
||||
dto.setData(source);
|
||||
dto.setUpdatedAt(updatedAt);
|
||||
sourceDao.insert(dto);
|
||||
addToCache(snapshot);
|
||||
}
|
||||
|
||||
@CheckForNull
|
||||
@ -61,16 +55,4 @@ public final class SourcePersister {
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private boolean isCached(Snapshot snapshot) {
|
||||
return savedSnapshotIds.contains(snapshot.getId());
|
||||
}
|
||||
|
||||
private void addToCache(Snapshot snapshot) {
|
||||
savedSnapshotIds.add(snapshot.getId());
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
savedSnapshotIds.clear();
|
||||
}
|
||||
}
|
||||
|
@ -42,10 +42,13 @@ import org.sonar.core.source.SnapshotDataTypes;
|
||||
import org.sonar.core.source.db.SnapshotDataDao;
|
||||
import org.sonar.core.source.db.SnapshotDataDto;
|
||||
|
||||
import javax.annotation.CheckForNull;
|
||||
import javax.persistence.NoResultException;
|
||||
import javax.persistence.Query;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@ -102,6 +105,7 @@ public class DefaultProjectReferentialsLoader implements ProjectReferentialsLoad
|
||||
ref.addFileData(module.getKeyWithBranch(), path, new FileData(hash, lastCommits, revisions, authors));
|
||||
}
|
||||
}
|
||||
ref.setLastAnalysisDate(lastSnapshotCreationDate(projectKey));
|
||||
return ref;
|
||||
}
|
||||
|
||||
@ -154,4 +158,33 @@ public class DefaultProjectReferentialsLoader implements ProjectReferentialsLoad
|
||||
}
|
||||
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 (Date) jpaQuery.getSingleResult();
|
||||
} catch (NoResultException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -26,6 +26,7 @@ import org.sonar.api.BatchComponent;
|
||||
import org.sonar.api.batch.SonarIndex;
|
||||
import org.sonar.api.batch.fs.FileSystem;
|
||||
import org.sonar.api.batch.fs.InputFile;
|
||||
import org.sonar.api.batch.fs.InputFile.Status;
|
||||
import org.sonar.api.batch.fs.internal.DeprecatedDefaultInputFile;
|
||||
import org.sonar.api.resources.File;
|
||||
import org.sonar.api.resources.Languages;
|
||||
@ -33,8 +34,13 @@ import org.sonar.api.resources.Project;
|
||||
import org.sonar.api.resources.Resource;
|
||||
import org.sonar.api.utils.SonarException;
|
||||
import org.sonar.batch.index.ResourceKeyMigration;
|
||||
import org.sonar.batch.index.SnapshotCache;
|
||||
import org.sonar.batch.index.SourcePersister;
|
||||
import org.sonar.batch.protocol.input.ProjectReferentials;
|
||||
import org.sonar.batch.util.DeprecatedKeyUtils;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* Index all files/directories of the module in SQ database and importing source code.
|
||||
*
|
||||
@ -46,12 +52,19 @@ public class ComponentIndexer implements BatchComponent {
|
||||
private final SonarIndex sonarIndex;
|
||||
private final ResourceKeyMigration migration;
|
||||
private final Project module;
|
||||
private final SourcePersister sourcePersister;
|
||||
private final ProjectReferentials projectReferentials;
|
||||
private final Date projectAnalysisDate;
|
||||
|
||||
public ComponentIndexer(Project module, Languages languages, SonarIndex sonarIndex, ResourceKeyMigration migration) {
|
||||
public ComponentIndexer(Project module, Languages languages, SonarIndex sonarIndex, ResourceKeyMigration migration, SourcePersister sourcePersister,
|
||||
ProjectReferentials projectReferentials, SnapshotCache snapshotCache) {
|
||||
this.module = module;
|
||||
this.languages = languages;
|
||||
this.sonarIndex = sonarIndex;
|
||||
this.migration = migration;
|
||||
this.sourcePersister = sourcePersister;
|
||||
this.projectReferentials = projectReferentials;
|
||||
this.projectAnalysisDate = snapshotCache.get(module.getEffectiveKey()).getBuildDate();
|
||||
}
|
||||
|
||||
public void execute(FileSystem fs) {
|
||||
@ -80,12 +93,16 @@ public class ComponentIndexer implements BatchComponent {
|
||||
void importSources(FileSystem fs, InputFile inputFile, Resource sonarFile) {
|
||||
try {
|
||||
// TODO this part deserves optimization.
|
||||
// No need to read full content in memory when shouldImportSource=false
|
||||
// We should try to remove BOM and count lines in a single pass
|
||||
String source = Files.toString(inputFile.file(), fs.encoding());
|
||||
// SONAR-3860 Remove BOM character from source
|
||||
source = CharMatcher.anyOf("\uFEFF").removeFrom(source);
|
||||
sonarIndex.setSource(sonarFile, source);
|
||||
if (inputFile.status() == Status.SAME) {
|
||||
sourcePersister.saveSource(sonarFile, source, projectReferentials.lastAnalysisDate());
|
||||
} else {
|
||||
sourcePersister.saveSource(sonarFile, source, this.projectAnalysisDate);
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
throw new SonarException("Unable to read and import the source file : '" + inputFile.absolutePath() + "' with the charset : '"
|
||||
+ fs.encoding() + "'.", e);
|
||||
|
@ -22,9 +22,9 @@ package org.sonar.batch.index;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.sonar.api.database.model.Snapshot;
|
||||
import org.sonar.api.resources.DuplicatedSourceException;
|
||||
import org.sonar.api.resources.File;
|
||||
import org.sonar.api.resources.Resource;
|
||||
import org.sonar.api.utils.DateUtils;
|
||||
import org.sonar.core.persistence.AbstractDaoTestCase;
|
||||
import org.sonar.core.source.db.SnapshotSourceDao;
|
||||
|
||||
@ -48,14 +48,8 @@ public class SourcePersisterTest extends AbstractDaoTestCase {
|
||||
|
||||
@Test
|
||||
public void shouldSaveSource() {
|
||||
sourcePersister.saveSource(new File("org/foo/Bar.java"), "this is the file content");
|
||||
sourcePersister.saveSource(new File("org/foo/Bar.java"), "this is the file content", DateUtils.parseDateTime("2014-10-31T16:44:02+0100"));
|
||||
checkTables("shouldSaveSource", "snapshot_sources");
|
||||
}
|
||||
|
||||
@Test(expected = DuplicatedSourceException.class)
|
||||
public void shouldFailIfSourceSavedSeveralTimes() {
|
||||
File file = new File("org/foo/Bar.java");
|
||||
sourcePersister.saveSource(file, "this is the file content");
|
||||
sourcePersister.saveSource(file, "new content"); // fail
|
||||
}
|
||||
}
|
||||
|
@ -32,7 +32,9 @@ import org.sonar.batch.rule.ModuleQProfiles;
|
||||
import org.sonar.core.source.db.SnapshotDataDao;
|
||||
|
||||
import static org.mockito.Matchers.anyString;
|
||||
import static org.mockito.Mockito.doReturn;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
@ -49,7 +51,9 @@ public class DefaultProjectReferentialsLoaderTest {
|
||||
serverClient = mock(ServerClient.class);
|
||||
analysisMode = mock(AnalysisMode.class);
|
||||
loader = new DefaultProjectReferentialsLoader(mock(DatabaseSession.class), serverClient, analysisMode, mock(SnapshotDataDao.class));
|
||||
when(serverClient.request(anyString())).thenReturn("");
|
||||
loader = spy(loader);
|
||||
doReturn(null).when(loader).lastSnapshotCreationDate(anyString());
|
||||
when(serverClient.request(anyString())).thenReturn("{}");
|
||||
reactor = new ProjectReactor(ProjectDefinition.create().setKey("foo"));
|
||||
taskProperties = new TaskProperties(Maps.<String, String>newHashMap(), "");
|
||||
}
|
||||
|
@ -33,6 +33,7 @@ import org.sonar.api.batch.fs.InputFile;
|
||||
import org.sonar.api.batch.fs.internal.DefaultFileSystem;
|
||||
import org.sonar.api.batch.fs.internal.DefaultInputFile;
|
||||
import org.sonar.api.batch.fs.internal.DeprecatedDefaultInputFile;
|
||||
import org.sonar.api.database.model.Snapshot;
|
||||
import org.sonar.api.resources.AbstractLanguage;
|
||||
import org.sonar.api.resources.Java;
|
||||
import org.sonar.api.resources.Languages;
|
||||
@ -40,10 +41,14 @@ import org.sonar.api.resources.Project;
|
||||
import org.sonar.api.resources.Qualifiers;
|
||||
import org.sonar.api.resources.Resource;
|
||||
import org.sonar.batch.index.ResourceKeyMigration;
|
||||
import org.sonar.batch.index.SnapshotCache;
|
||||
import org.sonar.batch.index.SourcePersister;
|
||||
import org.sonar.batch.protocol.input.ProjectReferentials;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.Date;
|
||||
|
||||
import static org.mockito.Matchers.argThat;
|
||||
import static org.mockito.Matchers.eq;
|
||||
@ -62,12 +67,14 @@ public class ComponentIndexerTest {
|
||||
|
||||
String aClaess;
|
||||
String explicacao;
|
||||
private SourcePersister sourcePersister;
|
||||
|
||||
@Before
|
||||
public void prepare() throws IOException {
|
||||
baseDir = temp.newFolder();
|
||||
sonarIndex = mock(SonarIndex.class);
|
||||
project = mock(Project.class);
|
||||
sourcePersister = mock(SourcePersister.class);
|
||||
project = new Project("myProject");
|
||||
cobolLanguage = new AbstractLanguage("cobol") {
|
||||
@Override
|
||||
public String[] getFileSuffixes() {
|
||||
@ -85,7 +92,7 @@ public class ComponentIndexerTest {
|
||||
fs.add(newInputFile("src/main/java2/foo/bar/Foo.java", "", "foo/bar/Foo.java", "java", false));
|
||||
fs.add(newInputFile("src/test/java/foo/bar/FooTest.java", "", "foo/bar/FooTest.java", "java", true));
|
||||
Languages languages = new Languages(Java.INSTANCE);
|
||||
ComponentIndexer indexer = new ComponentIndexer(project, languages, sonarIndex, mock(ResourceKeyMigration.class));
|
||||
ComponentIndexer indexer = createIndexer(languages);
|
||||
indexer.execute(fs);
|
||||
|
||||
verify(sonarIndex).index(org.sonar.api.resources.File.create("src/main/java/foo/bar/Foo.java", "foo/bar/Foo.java", Java.INSTANCE, false));
|
||||
@ -101,6 +108,14 @@ public class ComponentIndexerTest {
|
||||
}));
|
||||
}
|
||||
|
||||
private ComponentIndexer createIndexer(Languages languages) {
|
||||
SnapshotCache snapshotCache = new SnapshotCache();
|
||||
snapshotCache.put("myProject", mock(Snapshot.class));
|
||||
ComponentIndexer indexer = new ComponentIndexer(project, languages, sonarIndex, mock(ResourceKeyMigration.class), sourcePersister, new ProjectReferentials(),
|
||||
snapshotCache);
|
||||
return indexer;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void should_index_cobol_files() throws IOException {
|
||||
fs.add(newInputFile("src/foo/bar/Foo.cbl", "", "foo/bar/Foo.cbl", "cobol", false));
|
||||
@ -108,7 +123,7 @@ public class ComponentIndexerTest {
|
||||
fs.add(newInputFile("src/test/foo/bar/FooTest.cbl", "", "foo/bar/FooTest.cbl", "cobol", true));
|
||||
|
||||
Languages languages = new Languages(cobolLanguage);
|
||||
ComponentIndexer indexer = new ComponentIndexer(project, languages, sonarIndex, mock(ResourceKeyMigration.class));
|
||||
ComponentIndexer indexer = createIndexer(languages);
|
||||
indexer.execute(fs);
|
||||
|
||||
verify(sonarIndex).index(org.sonar.api.resources.File.create("/src/foo/bar/Foo.cbl", "foo/bar/Foo.cbl", cobolLanguage, false));
|
||||
@ -120,12 +135,12 @@ public class ComponentIndexerTest {
|
||||
public void shouldImportSource() throws IOException {
|
||||
fs.add(newInputFile("src/main/java/foo/bar/Foo.java", "sample code", "foo/bar/Foo.java", "java", false));
|
||||
Languages languages = new Languages(Java.INSTANCE);
|
||||
ComponentIndexer indexer = new ComponentIndexer(project, languages, sonarIndex, mock(ResourceKeyMigration.class));
|
||||
ComponentIndexer indexer = createIndexer(languages);
|
||||
indexer.execute(fs);
|
||||
|
||||
Resource sonarFile = org.sonar.api.resources.File.create("src/main/java/foo/bar/Foo.java", "foo/bar/Foo.java", Java.INSTANCE, false);
|
||||
verify(sonarIndex).index(sonarFile);
|
||||
verify(sonarIndex).setSource(sonarFile, "sample code");
|
||||
verify(sourcePersister).saveSource(sonarFile, "sample code", null);
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -158,18 +173,18 @@ public class ComponentIndexerTest {
|
||||
.setFile(javaFile1)
|
||||
.setLanguage("java"));
|
||||
Languages languages = new Languages(Java.INSTANCE);
|
||||
ComponentIndexer indexer = new ComponentIndexer(project, languages, sonarIndex, mock(ResourceKeyMigration.class));
|
||||
ComponentIndexer indexer = createIndexer(languages);
|
||||
indexer.execute(fs);
|
||||
|
||||
Resource sonarFile = org.sonar.api.resources.File.create("src/main/java/foo/bar/Foo.java", "foo/bar/Foo.java", Java.INSTANCE, false);
|
||||
|
||||
verify(sonarIndex).setSource(eq(sonarFile), argThat(new ArgumentMatcher<String>() {
|
||||
verify(sourcePersister).saveSource(eq(sonarFile), argThat(new ArgumentMatcher<String>() {
|
||||
@Override
|
||||
public boolean matches(Object arg0) {
|
||||
String source = (String) arg0;
|
||||
return !source.contains("\uFEFF");
|
||||
}
|
||||
}));
|
||||
}), (Date) eq(null));
|
||||
}
|
||||
|
||||
private void fileEncodingTest(String encoding, String testFile) throws Exception {
|
||||
@ -182,18 +197,18 @@ public class ComponentIndexerTest {
|
||||
.setFile(javaFile1)
|
||||
.setLanguage("java"));
|
||||
Languages languages = new Languages(Java.INSTANCE);
|
||||
ComponentIndexer indexer = new ComponentIndexer(project, languages, sonarIndex, mock(ResourceKeyMigration.class));
|
||||
ComponentIndexer indexer = createIndexer(languages);
|
||||
indexer.execute(fs);
|
||||
|
||||
Resource sonarFile = org.sonar.api.resources.File.create("/src/main/java/foo/bar/Foo.java", "foo/bar/Foo.java", Java.INSTANCE, false);
|
||||
|
||||
verify(sonarIndex).setSource(eq(sonarFile), argThat(new ArgumentMatcher<String>() {
|
||||
verify(sourcePersister).saveSource(eq(sonarFile), argThat(new ArgumentMatcher<String>() {
|
||||
@Override
|
||||
public boolean matches(Object arg0) {
|
||||
String source = (String) arg0;
|
||||
return source.contains(aClaess) && source.contains(explicacao);
|
||||
}
|
||||
}));
|
||||
}), (Date) eq(null));
|
||||
}
|
||||
|
||||
private File getFile(String testFile) {
|
||||
|
@ -35,6 +35,7 @@ public class FileMetadataTest {
|
||||
private static final String EXPECTED_HASH_WITHOUT_LATEST_EOL = "c80cc50d65ace6c4eb63f189d274dbeb";
|
||||
private static final String EXPECTED_HASH_NEW_LINE_FIRST = "cf2d41454b5b451eeb5122f0848c1d2a";
|
||||
private static final String EXPECTED_HASH_WITH_LATEST_EOL = "bf77e51d219e7d7d643faac86f1b5d15";
|
||||
private static final String NON_ASCII = "4050369e8ba432c9079e258b43fe4ab5";
|
||||
|
||||
@Rule
|
||||
public ExpectedException thrown = ExpectedException.none();
|
||||
@ -63,13 +64,23 @@ public class FileMetadataTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void windows_with_latest_eol() throws Exception {
|
||||
public void non_ascii_utf_8() throws Exception {
|
||||
File tempFile = temp.newFile();
|
||||
FileUtils.write(tempFile, "foo\r\nbar\r\nbaz\r\n", Charsets.UTF_8, true);
|
||||
FileUtils.write(tempFile, "föo\r\nbàr\r\n\u1D11Ebaßz\r\n", Charsets.UTF_8, true);
|
||||
|
||||
FileMetadata.Metadata metadata = FileMetadata.INSTANCE.read(tempFile, Charsets.UTF_8);
|
||||
assertThat(metadata.lines).isEqualTo(4);
|
||||
assertThat(metadata.hash).isEqualTo(EXPECTED_HASH_WITH_LATEST_EOL);
|
||||
assertThat(metadata.hash).isEqualTo(NON_ASCII);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void non_ascii_utf_16() throws Exception {
|
||||
File tempFile = temp.newFile();
|
||||
FileUtils.write(tempFile, "föo\r\nbàr\r\n\u1D11Ebaßz\r\n", Charsets.UTF_16, true);
|
||||
|
||||
FileMetadata.Metadata metadata = FileMetadata.INSTANCE.read(tempFile, Charsets.UTF_16);
|
||||
assertThat(metadata.lines).isEqualTo(4);
|
||||
assertThat(metadata.hash).isEqualTo(NON_ASCII);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -8,5 +8,5 @@
|
||||
scope="FIL" qualifier="CLA" created_at="2008-11-01 13:58:00.00" build_date="2008-11-01 13:58:00.00" version="[null]" path=""
|
||||
status="U" islast="[false]" depth="3" />
|
||||
|
||||
<SNAPSHOT_SOURCES ID="1" SNAPSHOT_ID="1000" DATA="this is the file content" UPDATED_AT="[null]"/>
|
||||
<SNAPSHOT_SOURCES ID="1" SNAPSHOT_ID="1000" DATA="this is the file content" updated_at="2014-10-31 16:44:02.000"/>
|
||||
</dataset>
|
||||
|
@ -19,10 +19,13 @@
|
||||
*/
|
||||
package org.sonar.core.source.db;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
public class SnapshotSourceDto {
|
||||
private Long id;
|
||||
private Long snapshotId;
|
||||
private String data;
|
||||
private Date updatedAt;
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
@ -50,4 +53,13 @@ public class SnapshotSourceDto {
|
||||
this.data = data;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Date getUpdatedAt() {
|
||||
return updatedAt;
|
||||
}
|
||||
|
||||
public SnapshotSourceDto setUpdatedAt(Date updatedAt) {
|
||||
this.updatedAt = updatedAt;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
@ -19,7 +19,8 @@
|
||||
</select>
|
||||
|
||||
<insert id="insert" parameterType="org.sonar.core.source.db.SnapshotSourceDto" useGeneratedKeys="false">
|
||||
insert into snapshot_sources (snapshot_id, data) values (#{snapshotId}, #{data})
|
||||
insert into snapshot_sources (snapshot_id, data, updated_at)
|
||||
values (#{snapshotId}, #{data}, #{updatedAt})
|
||||
</insert>
|
||||
|
||||
</mapper>
|
||||
|
@ -22,6 +22,7 @@ package org.sonar.core.source.db;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.sonar.api.utils.DateUtils;
|
||||
import org.sonar.core.persistence.AbstractDaoTestCase;
|
||||
|
||||
import static org.fest.assertions.Assertions.assertThat;
|
||||
@ -52,7 +53,7 @@ public class SnapshotSourceDaoTest extends AbstractDaoTestCase {
|
||||
|
||||
@Test
|
||||
public void insert() throws Exception {
|
||||
dao.insert(new SnapshotSourceDto().setId(102L).setData("bar").setSnapshotId(11L));
|
||||
dao.insert(new SnapshotSourceDto().setId(102L).setData("bar").setSnapshotId(11L).setUpdatedAt(DateUtils.parseDateTime("2014-10-31T16:44:02+0100")));
|
||||
|
||||
checkTable("insert", "snapshot_sources");
|
||||
}
|
||||
|
@ -5,8 +5,8 @@
|
||||
<snapshots id="10" project_id="1" islast="[false]"/>
|
||||
<snapshots id="11" project_id="1" islast="[true]"/>
|
||||
|
||||
<snapshot_sources id="101" snapshot_id="11" data="public class Foo {public Foo(){}}" updated_at="[null]"/>
|
||||
<snapshot_sources id="101" snapshot_id="11" data="public class Foo {public Foo(){}}" updated_at="2014-10-30 16:44:02.000"/>
|
||||
|
||||
<snapshot_sources id="102" snapshot_id="11" data="bar" updated_at="[null]"/>
|
||||
<snapshot_sources id="102" snapshot_id="11" data="bar" updated_at="2014-10-31 16:44:02.000"/>
|
||||
|
||||
</dataset>
|
||||
|
@ -5,6 +5,6 @@
|
||||
<snapshots id="10" project_id="1" islast="[false]" />
|
||||
<snapshots id="11" project_id="1" islast="[true]" />
|
||||
|
||||
<snapshot_sources id="101" snapshot_id="11" data="public class Foo {public Foo(){}}" />
|
||||
<snapshot_sources id="101" snapshot_id="11" data="public class Foo {public Foo(){}}" updated_at="2014-10-30 16:44:02.000" />
|
||||
|
||||
</dataset>
|
||||
|
@ -93,20 +93,9 @@ public abstract class SonarIndex implements DirectedGraphAccessor<Resource, Depe
|
||||
|
||||
public abstract Collection<Resource> getChildren(Resource reference);
|
||||
|
||||
/**
|
||||
* Save the source code of a file. The file must be have been indexed before.
|
||||
* Note: the source stream is not closed.
|
||||
*
|
||||
* @throws org.sonar.api.resources.DuplicatedSourceException
|
||||
* if the source has already been set on this resource
|
||||
* @deprecated since 4.2 should not be used by plugins
|
||||
*/
|
||||
@Deprecated
|
||||
public abstract void setSource(Resource reference, String source);
|
||||
|
||||
/**
|
||||
* @return source code associated with a specified resource, <code>null</code> if not available
|
||||
* (for example when sonar.importSources=false)
|
||||
* (for example if resource is not a file)
|
||||
* @since 2.9
|
||||
*/
|
||||
@CheckForNull
|
||||
|
Loading…
Reference in New Issue
Block a user