]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-6281 Fix branch and keys of components in compute report
authorJulien HENRY <julien.henry@sonarsource.com>
Mon, 1 Jun 2015 10:57:09 +0000 (12:57 +0200)
committerJulien HENRY <julien.henry@sonarsource.com>
Mon, 1 Jun 2015 11:18:19 +0000 (13:18 +0200)
sonar-batch/src/main/java/org/sonar/batch/DefaultProjectTree.java
sonar-batch/src/main/java/org/sonar/batch/index/BatchComponent.java
sonar-batch/src/main/java/org/sonar/batch/index/BatchComponentCache.java
sonar-batch/src/main/java/org/sonar/batch/report/ComponentsPublisher.java
sonar-batch/src/main/java/org/sonar/batch/report/IssuesPublisher.java
sonar-batch/src/main/java/org/sonar/batch/scan/ImmutableProjectReactor.java
sonar-batch/src/main/java/org/sonar/batch/scan/ImmutableProjectReactorProvider.java
sonar-batch/src/test/java/org/sonar/batch/report/ComponentsPublisherTest.java
sonar-batch/src/test/java/org/sonar/batch/report/IssuesPublisherTest.java

index 343ecb787ed0b561f1201d482a811307f59c3613..b520c1bcf17d2abfef041f1962b318b177cd652b 100644 (file)
@@ -21,15 +21,15 @@ package org.sonar.batch;
 
 import com.google.common.collect.Lists;
 import com.google.common.collect.Maps;
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
 import org.apache.commons.lang.ObjectUtils;
 import org.picocontainer.Startable;
 import org.sonar.api.batch.bootstrap.ProjectDefinition;
 import org.sonar.api.resources.Project;
 import org.sonar.batch.scan.ImmutableProjectReactor;
 
-import java.util.List;
-import java.util.Map;
-
 public class DefaultProjectTree implements Startable {
 
   private final ProjectConfigurator configurator;
@@ -53,7 +53,7 @@ public class DefaultProjectTree implements Startable {
     // Nothing to do
   }
 
-  void doStart(List<ProjectDefinition> definitions) {
+  void doStart(Collection<ProjectDefinition> definitions) {
     projects = Lists.newArrayList();
     projectsByDef = Maps.newHashMap();
 
index 38655cc298b9e3bd69cad96525a6919efd24c68c..5dc04e22c5f86d0ab44a73677acd78fe59e680bf 100644 (file)
  */
 package org.sonar.batch.index;
 
+import java.util.ArrayList;
+import java.util.Collection;
+import javax.annotation.CheckForNull;
+import javax.annotation.Nullable;
 import org.apache.commons.lang.StringUtils;
 import org.sonar.api.batch.fs.InputPath;
 import org.sonar.api.database.model.Snapshot;
 import org.sonar.api.resources.Qualifiers;
 import org.sonar.api.resources.Resource;
-
-import javax.annotation.CheckForNull;
-import javax.annotation.Nullable;
-
-import java.util.ArrayList;
-import java.util.Collection;
+import org.sonar.api.resources.ResourceUtils;
 
 public class BatchComponent {
 
@@ -104,4 +103,8 @@ public class BatchComponent {
   public InputPath inputPath() {
     return inputPath;
   }
+
+  public boolean isProjectOrModule() {
+    return ResourceUtils.isProject(r);
+  }
 }
index f030027e24fb0ede596926ef2eff02ed67f363f9..67c7b28c38e4120ac051ef4fcf4ebb38764b0789 100644 (file)
@@ -59,13 +59,12 @@ public class BatchComponentCache {
     String componentKey = resource.getEffectiveKey();
     Preconditions.checkState(!Strings.isNullOrEmpty(componentKey), "Missing resource effective key");
     BatchComponent parent = parentResource != null ? get(parentResource.getEffectiveKey()) : null;
-    BatchComponent batchResource = new BatchComponent(components.size() + 1, resource, parent);
-    // Libraries can have the same effective key than a project so we can't cache by effectiveKey
-    components.put(componentKey, batchResource);
+    BatchComponent batchComponent = new BatchComponent(components.size() + 1, resource, parent);
+    components.put(componentKey, batchComponent);
     if (parent == null) {
-      root = batchResource;
+      root = batchComponent;
     }
-    return batchResource;
+    return batchComponent;
   }
 
   public Collection<BatchComponent> all() {
index adbff2ffaaa60d52425c224c3351d1f679c3ebb2..446e7f0857d214d61b2e197aaeff0b0fa28e76f5 100644 (file)
@@ -23,7 +23,6 @@ import javax.annotation.CheckForNull;
 import org.apache.commons.lang.StringUtils;
 import org.sonar.api.CoreProperties;
 import org.sonar.api.batch.bootstrap.ProjectDefinition;
-import org.sonar.api.batch.bootstrap.ProjectReactor;
 import org.sonar.api.batch.fs.InputFile;
 import org.sonar.api.resources.Language;
 import org.sonar.api.resources.Resource;
@@ -37,6 +36,7 @@ import org.sonar.batch.protocol.output.BatchReport.Component.Builder;
 import org.sonar.batch.protocol.output.BatchReport.ComponentLink;
 import org.sonar.batch.protocol.output.BatchReport.Event;
 import org.sonar.batch.protocol.output.BatchReportWriter;
+import org.sonar.batch.scan.ImmutableProjectReactor;
 
 /**
  * Adds components and analysis metadata to output report
@@ -44,10 +44,10 @@ import org.sonar.batch.protocol.output.BatchReportWriter;
 public class ComponentsPublisher implements ReportPublisherStep {
 
   private final BatchComponentCache resourceCache;
-  private final ProjectReactor reactor;
+  private final ImmutableProjectReactor reactor;
   private final EventCache eventCache;
 
-  public ComponentsPublisher(ProjectReactor reactor, BatchComponentCache resourceCache, EventCache eventCache) {
+  public ComponentsPublisher(ImmutableProjectReactor reactor, BatchComponentCache resourceCache, EventCache eventCache) {
     this.reactor = reactor;
     this.resourceCache = resourceCache;
     this.eventCache = eventCache;
@@ -59,28 +59,30 @@ public class ComponentsPublisher implements ReportPublisherStep {
     recursiveWriteComponent(rootProject, writer);
   }
 
-  private void recursiveWriteComponent(BatchComponent batchResource, BatchReportWriter writer) {
-    Resource r = batchResource.resource();
+  private void recursiveWriteComponent(BatchComponent batchComponent, BatchReportWriter writer) {
+    Resource r = batchComponent.resource();
     BatchReport.Component.Builder builder = BatchReport.Component.newBuilder();
 
     // non-null fields
-    builder.setRef(batchResource.batchId());
+    builder.setRef(batchComponent.batchId());
     builder.setType(getType(r));
 
     // Don't set key on directories and files to save space since it can be deduced from path
-    if (ResourceUtils.isProject(r)) {
-      builder.setKey(r.getKey());
+    if (batchComponent.isProjectOrModule()) {
+      // Here we want key without branch
+      ProjectDefinition def = reactor.getProjectDefinition(batchComponent.key());
+      builder.setKey(def.getKey());
     }
 
     // protocol buffers does not accept null values
 
-    Integer sid = batchResource.snapshotId();
+    Integer sid = batchComponent.snapshotId();
     if (sid != null) {
       builder.setSnapshotId(sid);
     }
-    if (batchResource.isFile()) {
+    if (batchComponent.isFile()) {
       builder.setIsTest(ResourceUtils.isUnitTestFile(r));
-      builder.setLines(((InputFile) batchResource.inputPath()).lines());
+      builder.setLines(((InputFile) batchComponent.inputPath()).lines());
     }
     String name = getName(r);
     if (name != null) {
@@ -98,15 +100,15 @@ public class ComponentsPublisher implements ReportPublisherStep {
     if (lang != null) {
       builder.setLanguage(lang);
     }
-    for (BatchComponent child : batchResource.children()) {
+    for (BatchComponent child : batchComponent.children()) {
       builder.addChildRef(child.batchId());
     }
-    writeLinks(r, builder);
-    writeVersion(r, builder);
-    writeEvents(batchResource, builder);
+    writeLinks(batchComponent, builder);
+    writeVersion(batchComponent, builder);
+    writeEvents(batchComponent, builder);
     writer.writeComponent(builder.build());
 
-    for (BatchComponent child : batchResource.children()) {
+    for (BatchComponent child : batchComponent.children()) {
       recursiveWriteComponent(child, writer);
     }
   }
@@ -119,9 +121,9 @@ public class ComponentsPublisher implements ReportPublisherStep {
     }
   }
 
-  private void writeVersion(Resource r, BatchReport.Component.Builder builder) {
-    if (ResourceUtils.isProject(r)) {
-      ProjectDefinition def = getProjectDefinition(reactor, r.getKey());
+  private void writeVersion(BatchComponent c, BatchReport.Component.Builder builder) {
+    if (c.isProjectOrModule()) {
+      ProjectDefinition def = reactor.getProjectDefinition(c.key());
       String version = getVersion(def);
       builder.setVersion(version);
     }
@@ -132,9 +134,9 @@ public class ComponentsPublisher implements ReportPublisherStep {
     return StringUtils.isNotBlank(version) ? version : getVersion(def.getParent());
   }
 
-  private void writeLinks(Resource r, BatchReport.Component.Builder builder) {
-    if (ResourceUtils.isProject(r)) {
-      ProjectDefinition def = getProjectDefinition(reactor, r.getKey());
+  private void writeLinks(BatchComponent c, BatchReport.Component.Builder builder) {
+    if (c.isProjectOrModule()) {
+      ProjectDefinition def = reactor.getProjectDefinition(c.key());
       ComponentLink.Builder linkBuilder = ComponentLink.newBuilder();
 
       writeProjectLink(builder, def, linkBuilder, CoreProperties.LINKS_HOME_PAGE, ComponentLinkType.HOME);
@@ -145,15 +147,6 @@ public class ComponentsPublisher implements ReportPublisherStep {
     }
   }
 
-  private ProjectDefinition getProjectDefinition(ProjectReactor reactor, String keyWithBranch) {
-    for (ProjectDefinition p : reactor.getProjects()) {
-      if (keyWithBranch.equals(p.getKeyWithBranch())) {
-        return p;
-      }
-    }
-    return null;
-  }
-
   private void writeProjectLink(BatchReport.Component.Builder componentBuilder, ProjectDefinition def, ComponentLink.Builder linkBuilder, String linkProp,
     ComponentLinkType linkType) {
     String link = def.properties().get(linkProp);
index e2c70d590db258ad7a6597b3f0373b4803e38f42..9af7a18fe127c529d105e6d699e0bdf53dfdf74e 100644 (file)
@@ -21,7 +21,12 @@ package org.sonar.batch.report;
 
 import com.google.common.base.Function;
 import com.google.common.collect.Iterables;
-import org.sonar.api.batch.bootstrap.ProjectReactor;
+import java.util.Collection;
+import java.util.Date;
+import java.util.Iterator;
+import javax.annotation.Nullable;
+import org.sonar.api.CoreProperties;
+import org.sonar.api.batch.bootstrap.ProjectDefinition;
 import org.sonar.api.issue.internal.DefaultIssue;
 import org.sonar.api.issue.internal.FieldDiffs;
 import org.sonar.api.resources.Project;
@@ -32,29 +37,24 @@ import org.sonar.batch.issue.IssueCache;
 import org.sonar.batch.protocol.Constants;
 import org.sonar.batch.protocol.output.BatchReport;
 import org.sonar.batch.protocol.output.BatchReportWriter;
-
-import javax.annotation.Nullable;
-
-import java.util.Collection;
-import java.util.Date;
-import java.util.Iterator;
+import org.sonar.batch.scan.ImmutableProjectReactor;
 
 public class IssuesPublisher implements ReportPublisherStep {
 
-  private final BatchComponentCache resourceCache;
+  private final BatchComponentCache componentCache;
   private final IssueCache issueCache;
-  private final ProjectReactor reactor;
+  private final ImmutableProjectReactor reactor;
 
-  public IssuesPublisher(ProjectReactor reactor, BatchComponentCache resourceCache, IssueCache issueCache) {
+  public IssuesPublisher(ImmutableProjectReactor reactor, BatchComponentCache componentCache, IssueCache issueCache) {
     this.reactor = reactor;
-    this.resourceCache = resourceCache;
+    this.componentCache = componentCache;
     this.issueCache = issueCache;
   }
 
   @Override
   public void publish(BatchReportWriter writer) {
     Collection<Object> deletedComponentKeys = issueCache.componentKeys();
-    for (BatchComponent resource : resourceCache.all()) {
+    for (BatchComponent resource : componentCache.all()) {
       String componentKey = resource.resource().getEffectiveKey();
       Iterable<DefaultIssue> issues = issueCache.byComponent(componentKey);
       writer.writeComponentIssues(resource.batchId(), Iterables.transform(issues, new Function<DefaultIssue, BatchReport.Issue>() {
@@ -74,12 +74,18 @@ public class IssuesPublisher implements ReportPublisherStep {
   }
 
   private void exportMetadata(BatchReportWriter writer, int count) {
-    BatchComponent rootProject = resourceCache.get(reactor.getRoot().getKeyWithBranch());
+    ProjectDefinition root = reactor.getRoot();
+    BatchComponent rootProject = componentCache.getRoot();
     BatchReport.Metadata.Builder builder = BatchReport.Metadata.newBuilder()
       .setAnalysisDate(((Project) rootProject.resource()).getAnalysisDate().getTime())
-      .setProjectKey(((Project) rootProject.resource()).key())
+      // Here we want key without branch
+      .setProjectKey(root.getKey())
       .setRootComponentRef(rootProject.batchId())
       .setDeletedComponentsCount(count);
+    String branch = root.properties().get(CoreProperties.PROJECT_BRANCH_PROPERTY);
+    if (branch != null) {
+      builder.setBranch(branch);
+    }
     Integer sid = rootProject.snapshotId();
     if (sid != null) {
       builder.setSnapshotId(sid);
index f99242078b0047a12216f4a8af66679ffc6e42c5..687fb639b94b4749c530a62a4205237ddda3708c 100644 (file)
  */
 package org.sonar.batch.scan;
 
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
+import javax.annotation.CheckForNull;
 import org.sonar.api.batch.BatchSide;
 import org.sonar.api.batch.bootstrap.ProjectDefinition;
 
-import java.util.ArrayList;
-import java.util.List;
-
 /**
  * Immutable copy of project reactor after all modifications have been applied (see {@link MutableProjectReactorProvider}).
  */
@@ -32,39 +33,39 @@ import java.util.List;
 public class ImmutableProjectReactor {
 
   private ProjectDefinition root;
+  private Map<String, ProjectDefinition> byKey = new HashMap<>();
 
   public ImmutableProjectReactor(ProjectDefinition root) {
     if (root.getParent() != null) {
       throw new IllegalArgumentException("Not a root project: " + root);
     }
     this.root = root;
+    collectProjects(root);
   }
 
-  public List<ProjectDefinition> getProjects() {
-    return collectProjects(root, new ArrayList<ProjectDefinition>());
+  public Collection<ProjectDefinition> getProjects() {
+    return byKey.values();
   }
 
   /**
    * Populates list of projects from hierarchy.
    */
-  private static List<ProjectDefinition> collectProjects(ProjectDefinition def, List<ProjectDefinition> collected) {
-    collected.add(def);
+  private void collectProjects(ProjectDefinition def) {
+    if (byKey.containsKey(def.getKeyWithBranch())) {
+      throw new IllegalStateException("Duplicate module key in reactor: " + def.getKeyWithBranch());
+    }
+    byKey.put(def.getKeyWithBranch(), def);
     for (ProjectDefinition child : def.getSubProjects()) {
-      collectProjects(child, collected);
+      collectProjects(child);
     }
-    return collected;
   }
 
   public ProjectDefinition getRoot() {
     return root;
   }
 
-  public ProjectDefinition getProject(String key) {
-    for (ProjectDefinition p : getProjects()) {
-      if (key.equals(p.getKey())) {
-        return p;
-      }
-    }
-    return null;
+  @CheckForNull
+  public ProjectDefinition getProjectDefinition(String keyWithBranch) {
+    return byKey.get(keyWithBranch);
   }
 }
index 6ca8bf9f9924db8f7398c19e1c4ac8e84da733ca..b3efa876b543b99b6cb9402823dcee25d0524334 100644 (file)
@@ -24,17 +24,21 @@ import org.sonar.api.batch.bootstrap.ProjectReactor;
 
 public class ImmutableProjectReactorProvider extends ProviderAdapter {
 
-  public ImmutableProjectReactor provide(ProjectReactor reactor, ProjectBuildersExecutor projectBuildersExecutor, ProjectExclusions exclusions, ProjectReactorValidator validator) {
+  private ImmutableProjectReactor singleton;
 
-    // 1 Apply project builders
-    projectBuildersExecutor.execute(reactor);
+  public ImmutableProjectReactor provide(ProjectReactor reactor, ProjectBuildersExecutor projectBuildersExecutor, ProjectExclusions exclusions, ProjectReactorValidator validator) {
+    if (singleton == null) {
+      // 1 Apply project builders
+      projectBuildersExecutor.execute(reactor);
 
-    // 2 Apply project exclusions
-    exclusions.apply(reactor);
+      // 2 Apply project exclusions
+      exclusions.apply(reactor);
 
-    // 3 Validate final reactor
-    validator.validate(reactor);
+      // 3 Validate final reactor
+      validator.validate(reactor);
 
-    return new ImmutableProjectReactor(reactor.getRoot());
+      singleton = new ImmutableProjectReactor(reactor.getRoot());
+    }
+    return singleton;
   }
 }
index 9d60874d175d364c2b346b516703b2c47ebf75d8..50e9b1df64ff458c3072c64cc931b5a5f3fe4589 100644 (file)
@@ -27,7 +27,6 @@ import org.junit.Test;
 import org.junit.rules.TemporaryFolder;
 import org.sonar.api.CoreProperties;
 import org.sonar.api.batch.bootstrap.ProjectDefinition;
-import org.sonar.api.batch.bootstrap.ProjectReactor;
 import org.sonar.api.batch.fs.internal.DefaultInputFile;
 import org.sonar.api.database.model.Snapshot;
 import org.sonar.api.resources.Directory;
@@ -42,6 +41,7 @@ import org.sonar.batch.protocol.output.BatchReport.Event;
 import org.sonar.batch.protocol.output.BatchReportReader;
 import org.sonar.batch.protocol.output.BatchReportWriter;
 import org.sonar.batch.protocol.output.FileStructure;
+import org.sonar.batch.scan.ImmutableProjectReactor;
 
 import static org.assertj.core.api.Assertions.assertThat;
 import static org.mockito.Mockito.mock;
@@ -52,23 +52,20 @@ public class ComponentsPublisherTest {
   @Rule
   public TemporaryFolder temp = new TemporaryFolder();
 
-  private ProjectReactor reactor;
   private BatchComponentCache resourceCache;
-  private ComponentsPublisher publisher;
   private EventCache eventCache;
 
   @Before
   public void prepare() {
-    reactor = new ProjectReactor(ProjectDefinition.create().setKey("foo"));
-    reactor.getRoot().properties().put(CoreProperties.PROJECT_VERSION_PROPERTY, "1.0");
     resourceCache = new BatchComponentCache();
     eventCache = mock(EventCache.class);
-    publisher = new ComponentsPublisher(reactor, resourceCache, eventCache);
   }
 
   @Test
   public void add_components_to_report() throws Exception {
-    // inputs
+
+    ProjectDefinition rootDef = ProjectDefinition.create().setKey("foo");
+    rootDef.properties().put(CoreProperties.PROJECT_VERSION_PROPERTY, "1.0");
     Project root = new Project("foo").setName("Root project").setDescription("Root description")
       .setAnalysisDate(DateUtils.parseDate(("2012-12-12")));
     root.setId(1).setUuid("PROJECT_UUID");
@@ -78,7 +75,7 @@ public class ComponentsPublisherTest {
     module1.setParent(root);
     module1.setId(2).setUuid("MODULE_UUID");
     resourceCache.add(module1, root).setSnapshot(new Snapshot().setId(12));
-    reactor.getRoot().addSubProject(ProjectDefinition.create().setKey("module1"));
+    rootDef.addSubProject(ProjectDefinition.create().setKey("module1"));
 
     Directory dir = Directory.create("src");
     dir.setEffectiveKey("module1:src");
@@ -100,6 +97,10 @@ public class ComponentsPublisherTest {
     testFile.setId(6).setUuid("TEST_FILE_UUID");
     resourceCache.add(testFile, dir).setSnapshot(new Snapshot().setId(16)).setInputPath(new DefaultInputFile("module1", "test/FooTest.java").setLines(4));
 
+    ImmutableProjectReactor reactor = new ImmutableProjectReactor(rootDef);
+
+    ComponentsPublisher publisher = new ComponentsPublisher(reactor, resourceCache, eventCache);
+
     File outputDir = temp.newFolder();
     BatchReportWriter writer = new BatchReportWriter(outputDir);
     publisher.publish(writer);
@@ -130,12 +131,14 @@ public class ComponentsPublisherTest {
   @Test
   public void add_components_with_links_and_branch() throws Exception {
     // inputs
+    ProjectDefinition rootDef = ProjectDefinition.create().setKey("foo");
+    rootDef.properties().put(CoreProperties.PROJECT_VERSION_PROPERTY, "1.0");
     Project root = new Project("foo:my_branch").setName("Root project")
       .setAnalysisDate(DateUtils.parseDate(("2012-12-12")));
     root.setId(1).setUuid("PROJECT_UUID");
     resourceCache.add(root, null).setSnapshot(new Snapshot().setId(11));
-    reactor.getRoot().properties().put(CoreProperties.LINKS_HOME_PAGE, "http://home");
-    reactor.getRoot().properties().put(CoreProperties.PROJECT_BRANCH_PROPERTY, "my_branch");
+    rootDef.properties().put(CoreProperties.LINKS_HOME_PAGE, "http://home");
+    rootDef.properties().put(CoreProperties.PROJECT_BRANCH_PROPERTY, "my_branch");
 
     Project module1 = new Project("module1:my_branch").setName("Module1");
     module1.setParent(root);
@@ -143,7 +146,7 @@ public class ComponentsPublisherTest {
     resourceCache.add(module1, root).setSnapshot(new Snapshot().setId(12));
     ProjectDefinition moduleDef = ProjectDefinition.create().setKey("module1");
     moduleDef.properties().put(CoreProperties.LINKS_CI, "http://ci");
-    reactor.getRoot().addSubProject(moduleDef);
+    rootDef.addSubProject(moduleDef);
 
     Directory dir = Directory.create("src");
     dir.setEffectiveKey("module1:my_branch:my_branch:src");
@@ -155,6 +158,10 @@ public class ComponentsPublisherTest {
     file.setId(4).setUuid("FILE_UUID");
     resourceCache.add(file, dir).setSnapshot(new Snapshot().setId(14)).setInputPath(new DefaultInputFile("module1", "src/Foo.java").setLines(2));
 
+    ImmutableProjectReactor reactor = new ImmutableProjectReactor(rootDef);
+
+    ComponentsPublisher publisher = new ComponentsPublisher(reactor, resourceCache, eventCache);
+
     File outputDir = temp.newFolder();
     BatchReportWriter writer = new BatchReportWriter(outputDir);
     publisher.publish(writer);
@@ -176,6 +183,8 @@ public class ComponentsPublisherTest {
   @Test
   public void add_components_with_events() throws Exception {
     // inputs
+    ProjectDefinition rootDef = ProjectDefinition.create().setKey("foo");
+    rootDef.properties().put(CoreProperties.PROJECT_VERSION_PROPERTY, "1.0");
     Project root = new Project("foo").setName("Root project")
       .setAnalysisDate(DateUtils.parseDate(("2012-12-12")));
     root.setId(1).setUuid("PROJECT_UUID");
@@ -186,7 +195,7 @@ public class ComponentsPublisherTest {
     module1.setId(2).setUuid("MODULE_UUID");
     resourceCache.add(module1, root).setSnapshot(new Snapshot().setId(12));
     ProjectDefinition moduleDef = ProjectDefinition.create().setKey("module1");
-    reactor.getRoot().addSubProject(moduleDef);
+    rootDef.addSubProject(moduleDef);
 
     when(eventCache.getEvents(2)).thenReturn(Arrays.asList(Event.newBuilder().setName("name").setCategory(EventCategory.ALERT).setComponentRef(2).build()));
 
@@ -195,6 +204,10 @@ public class ComponentsPublisherTest {
     dir.setId(3).setUuid("DIR_UUID");
     resourceCache.add(dir, module1).setSnapshot(new Snapshot().setId(13));
 
+    ImmutableProjectReactor reactor = new ImmutableProjectReactor(rootDef);
+
+    ComponentsPublisher publisher = new ComponentsPublisher(reactor, resourceCache, eventCache);
+
     File outputDir = temp.newFolder();
     BatchReportWriter writer = new BatchReportWriter(outputDir);
     publisher.publish(writer);
index f4299ae0df695ec3fc7390cc1a2c0dc06307b62f..7f0b40c8d591fe67f7e16e469ea11a2657d0108e 100644 (file)
  */
 package org.sonar.batch.report;
 
+import java.io.File;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Date;
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.TemporaryFolder;
+import org.sonar.api.CoreProperties;
 import org.sonar.api.batch.bootstrap.ProjectDefinition;
-import org.sonar.api.batch.bootstrap.ProjectReactor;
 import org.sonar.api.database.model.Snapshot;
 import org.sonar.api.issue.internal.DefaultIssue;
 import org.sonar.api.issue.internal.FieldDiffs;
@@ -36,11 +40,7 @@ import org.sonar.batch.issue.IssueCache;
 import org.sonar.batch.protocol.output.BatchReport.Metadata;
 import org.sonar.batch.protocol.output.BatchReportReader;
 import org.sonar.batch.protocol.output.BatchReportWriter;
-
-import java.io.File;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.Date;
+import org.sonar.batch.scan.ImmutableProjectReactor;
 
 import static org.assertj.core.api.Assertions.assertThat;
 import static org.mockito.Matchers.anyString;
@@ -55,17 +55,21 @@ public class IssuesPublisherTest {
   private IssueCache issueCache;
   private IssuesPublisher publisher;
 
+  private ProjectDefinition root;
+
+  private Project p;
+
   @Before
   public void prepare() {
-    ProjectDefinition root = ProjectDefinition.create().setKey("foo");
-    Project p = new Project("foo").setAnalysisDate(new Date(1234567L));
-    BatchComponentCache resourceCache = new BatchComponentCache();
+    root = ProjectDefinition.create().setKey("foo");
+    p = new Project("foo").setAnalysisDate(new Date(1234567L));
+    BatchComponentCache componentCache = new BatchComponentCache();
     org.sonar.api.resources.Resource sampleFile = org.sonar.api.resources.File.create("src/Foo.php").setEffectiveKey("foo:src/Foo.php");
-    resourceCache.add(p, null).setSnapshot(new Snapshot().setId(2));
-    resourceCache.add(sampleFile, null);
+    componentCache.add(p, null).setSnapshot(new Snapshot().setId(2));
+    componentCache.add(sampleFile, p);
     issueCache = mock(IssueCache.class);
     when(issueCache.byComponent(anyString())).thenReturn(Collections.<DefaultIssue>emptyList());
-    publisher = new IssuesPublisher(new ProjectReactor(root), resourceCache, issueCache);
+    publisher = new IssuesPublisher(new ImmutableProjectReactor(root), componentCache, issueCache);
   }
 
   @Test
@@ -114,6 +118,26 @@ public class IssuesPublisherTest {
 
   }
 
+  @Test
+  public void publishMatadataWithBranch() throws Exception {
+    root.properties().put(CoreProperties.PROJECT_BRANCH_PROPERTY, "myBranch");
+    p.setKey("foo:myBranch");
+    p.setEffectiveKey("foo:myBranch");
+
+    File outputDir = temp.newFolder();
+    BatchReportWriter writer = new BatchReportWriter(outputDir);
+
+    publisher.publish(writer);
+
+    BatchReportReader reader = new BatchReportReader(outputDir);
+    Metadata metadata = reader.readMetadata();
+    assertThat(metadata.getAnalysisDate()).isEqualTo(1234567L);
+    assertThat(metadata.getProjectKey()).isEqualTo("foo");
+    assertThat(metadata.getBranch()).isEqualTo("myBranch");
+    assertThat(metadata.getDeletedComponentsCount()).isEqualTo(0);
+    assertThat(metadata.getSnapshotId()).isEqualTo(2);
+  }
+
   @Test
   public void publishIssuesOfDeletedComponents() throws Exception {