/**
* @throws IllegalStateException if branch has already been set
*/
- MutableAnalysisMetadataHolder setBranch(@Nullable Branch branch);
+ MutableAnalysisMetadataHolder setBranch(@Nullable Branch branch);
/**
* @throws IllegalStateException if project has already been set
*/
String getKey();
+ /**
+ * Returns the key as it will be displayed in the ui.
+ * If legacy branch feature is used, the key will contain the branch name
+ * If new branch feature is used, the key will not contain the branch name
+ */
+ // TODO to be renamed getKey() and rename existing getKey to getDbKey
+ String getPublicKey();
+
/**
* The component name.
*/
private final Status status;
private final String name;
private final String key;
+ private final String publicKey;
private final String uuid;
@CheckForNull
this.type = builder.type;
this.status = builder.status;
this.key = builder.key;
+ this.publicKey = builder.publicKey;
this.name = builder.name;
this.description = builder.description;
this.uuid = builder.uuid;
return key;
}
+ @Override
+ public String getPublicKey() {
+ return publicKey;
+ }
+
@Override
public String getName() {
return this.name;
private ReportAttributes reportAttributes;
private String uuid;
private String key;
+ private String publicKey;
private String name;
private String description;
private FileAttributes fileAttributes;
return this;
}
+ public Builder setPublicKey(String publicKey) {
+ this.publicKey = requireNonNull(publicKey);
+ return this;
+ }
+
public Builder setName(String name) {
this.name = requireNonNull(name, NAME_CANNOT_BE_NULL);
return this;
+++ /dev/null
-/*
- * SonarQube
- * Copyright (C) 2009-2017 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.server.computation.task.projectanalysis.component;
-
-import com.google.common.annotations.VisibleForTesting;
-import com.google.common.base.MoreObjects;
-import com.google.common.base.Optional;
-import com.google.common.base.Supplier;
-import java.util.function.Function;
-import javax.annotation.CheckForNull;
-import javax.annotation.Nullable;
-import org.sonar.db.component.ComponentDto;
-import org.sonar.db.component.SnapshotDto;
-import org.sonar.scanner.protocol.output.ScannerReport;
-
-import static com.google.common.base.Preconditions.checkArgument;
-import static com.google.common.collect.Iterables.toArray;
-import static java.lang.String.format;
-import static org.apache.commons.lang.StringUtils.trimToNull;
-import static org.sonar.core.component.ComponentKeys.createEffectiveKey;
-import static org.sonar.core.component.ComponentKeys.createKey;
-import static org.sonar.core.util.stream.MoreCollectors.toList;
-
-public class ComponentRootBuilder {
- private static final String DEFAULT_PROJECT_VERSION = "not provided";
-
- /**
- * Will supply the UUID for any component in the tree, given it's key.
- * <p>
- * The String argument of the {@link Function#apply(Object)} method is the component's key.
- * </p>
- */
- private final Function<String, String> uuidSupplier;
- /**
- * Will supply the {@link ScannerReport.Component} of all the components in the component tree as we crawl it from the
- * root.
- * <p>
- * The Integer argument of the {@link Function#apply(Object)} method is the component's ref.
- * </p>
- */
- private final Function<Integer, ScannerReport.Component> scannerComponentSupplier;
- /**
- * Will supply the ComponentDto of the project (if it exists) if we need it to get the name of the project
- *
- * @see #nameOfProject(ScannerReport.Component, String, Supplier)
- */
- private final Supplier<Optional<ComponentDto>> projectDtoSupplier;
- /**
- * Will supply the SnapshotDto of the base analysis of the project (if it exists) if we need it to get the version
- * of the project.
- * <p>
- * The String argument of the {@link Function#apply(Object)} method is the project's UUID.
- * </p>
- *
- * @see #createProjectVersion(ScannerReport.Component, String, Function)
- */
- private final Function<String, Optional<SnapshotDto>> analysisSupplier;
- @CheckForNull
- private final String branch;
-
- public ComponentRootBuilder(@Nullable String branch,
- Function<String, String> uuidSupplier,
- Function<Integer, ScannerReport.Component> scannerComponentSupplier,
- Supplier<Optional<ComponentDto>> projectDtoSupplier,
- Function<String, Optional<SnapshotDto>> analysisSupplier) {
- this.uuidSupplier = uuidSupplier;
- this.scannerComponentSupplier = scannerComponentSupplier;
- this.projectDtoSupplier = projectDtoSupplier;
- this.branch = branch;
- this.analysisSupplier = analysisSupplier;
- }
-
- public Component build(ScannerReport.Component reportProject, String projectKey) {
- return buildComponent(reportProject, projectKey);
- }
-
- private ComponentImpl buildComponent(ScannerReport.Component reportComponent, String latestModuleKey) {
- switch (reportComponent.getType()) {
- case PROJECT:
- return buildProjectComponent(reportComponent, latestModuleKey);
- case MODULE:
- String moduleKey = createKey(reportComponent.getKey(), branch);
- return buildOtherComponent(reportComponent, moduleKey, moduleKey);
- case DIRECTORY:
- case FILE:
- return buildOtherComponent(reportComponent, createEffectiveKey(latestModuleKey, reportComponent.getPath()), latestModuleKey);
- default:
- throw new IllegalArgumentException(format("Unsupported component type '%s'", reportComponent.getType()));
- }
- }
-
- private ComponentImpl buildProjectComponent(ScannerReport.Component reportComponent, String latestModuleKey) {
- ComponentImpl.Builder builder = createCommonBuilder(reportComponent, latestModuleKey, latestModuleKey);
- return builder
- .setName(nameOfProject(reportComponent, latestModuleKey, projectDtoSupplier))
- .setReportAttributes(createProjectReportAttributes(reportComponent, builder.getUuid(), analysisSupplier))
- .build();
- }
-
- private ComponentImpl buildOtherComponent(ScannerReport.Component reportComponent, String componentKey, String latestModuleKey) {
- return createCommonBuilder(reportComponent, componentKey, latestModuleKey)
- .setName(nameOfOthers(reportComponent, componentKey))
- .setReportAttributes(createOtherReportAttributes(reportComponent))
- .build();
- }
-
- private ComponentImpl.Builder createCommonBuilder(ScannerReport.Component reportComponent, String componentKey, String latestModuleKey) {
- return ComponentImpl.builder(convertType(reportComponent.getType()))
- .setUuid(uuidSupplier.apply(componentKey))
- .setKey(componentKey)
- .setStatus(convertStatus(reportComponent.getStatus()))
- .setDescription(trimToNull(reportComponent.getDescription()))
- .setFileAttributes(createFileAttributes(reportComponent))
- .addChildren(toArray(buildChildren(reportComponent, latestModuleKey), Component.class));
- }
-
- private Iterable<Component> buildChildren(ScannerReport.Component component, String latestModuleKey) {
- return component.getChildRefList()
- .stream()
- .map(componentRef -> buildComponent(scannerComponentSupplier.apply(componentRef), latestModuleKey))
- .collect(toList(component.getChildRefList().size()));
- }
-
- private static String nameOfProject(ScannerReport.Component project, String projectKey, Supplier<Optional<ComponentDto>> projectDtoSupplier) {
- String name = trimToNull(project.getName());
- if (name == null) {
- return projectDtoSupplier.get().transform(ComponentDto::name).or(projectKey);
- }
- return name;
- }
-
- private static String nameOfOthers(ScannerReport.Component reportComponent, String componentKey) {
- String name = trimToNull(reportComponent.getName());
- return name == null ? componentKey : name;
- }
-
- @VisibleForTesting
- static ReportAttributes createProjectReportAttributes(ScannerReport.Component component,
- String projectUuid, Function<String, Optional<SnapshotDto>> analysisSupplier) {
- return createCommonBuilder(component)
- .setVersion(createProjectVersion(component, projectUuid, analysisSupplier))
- .build();
- }
-
- private static String createProjectVersion(ScannerReport.Component component,
- String projectUuid, Function<String, Optional<SnapshotDto>> analysisSupplier) {
- String version = trimToNull(component.getVersion());
- if (version != null) {
- return version;
- }
- Optional<SnapshotDto> snapshotDto = analysisSupplier.apply(projectUuid);
- if (snapshotDto.isPresent()) {
- return MoreObjects.firstNonNull(snapshotDto.get().getVersion(), DEFAULT_PROJECT_VERSION);
- }
- return DEFAULT_PROJECT_VERSION;
- }
-
- @VisibleForTesting
- static ReportAttributes createOtherReportAttributes(ScannerReport.Component component) {
- return createCommonBuilder(component)
- .setVersion(trimToNull(component.getVersion()))
- .build();
- }
-
- private static ReportAttributes.Builder createCommonBuilder(ScannerReport.Component component) {
- return ReportAttributes.newBuilder(component.getRef())
- .setPath(trimToNull(component.getPath()));
- }
-
- @VisibleForTesting
- @CheckForNull
- static FileAttributes createFileAttributes(ScannerReport.Component component) {
- if (component.getType() != ScannerReport.Component.ComponentType.FILE) {
- return null;
- }
-
- checkArgument(component.getLines() > 0, "File '%s' has no line", component.getPath());
- return new FileAttributes(
- component.getIsTest(),
- trimToNull(component.getLanguage()),
- component.getLines());
- }
-
- static Component.Status convertStatus(ScannerReport.Component.FileStatus status) {
- switch(status) {
- case ADDED:
- return Component.Status.ADDED;
- case SAME:
- return Component.Status.SAME;
- case CHANGED:
- return Component.Status.CHANGED;
- case UNAVAILABLE:
- return Component.Status.UNAVAILABLE;
- case UNRECOGNIZED:
- default:
- throw new IllegalArgumentException("Unsupported ComponentType value " + status);
- }
- }
-
- @VisibleForTesting
- static Component.Type convertType(ScannerReport.Component.ComponentType type) {
- switch (type) {
- case PROJECT:
- return Component.Type.PROJECT;
- case MODULE:
- return Component.Type.MODULE;
- case DIRECTORY:
- return Component.Type.DIRECTORY;
- case FILE:
- return Component.Type.FILE;
- default:
- throw new IllegalArgumentException("Unsupported ComponentType value " + type);
- }
- }
-}
private static final String DEFAULT_PROJECT_VERSION = "not provided";
private final ComponentKeyGenerator keyGenerator;
+ private final ComponentKeyGenerator publicKeyGenerator;
/**
* Will supply the UUID for any component in the tree, given it's key.
* <p>
public ComponentTreeBuilder(
ComponentKeyGenerator keyGenerator,
+ ComponentKeyGenerator publicKeyGenerator,
Function<String, String> uuidSupplier,
Function<Integer, ScannerReport.Component> scannerComponentSupplier,
Project project,
@Nullable SnapshotDto baseAnalysis) {
this.keyGenerator = keyGenerator;
+ this.publicKeyGenerator = publicKeyGenerator;
this.uuidSupplier = uuidSupplier;
this.scannerComponentSupplier = scannerComponentSupplier;
this.project = project;
return ComponentImpl.builder(Component.Type.PROJECT)
.setUuid(uuid)
.setKey(projectKey)
+ .setPublicKey(publicKeyGenerator.generateKey(component, null))
.setName(nameOfProject(component))
.setStatus(convertStatus(component.getStatus()))
.setDescription(trimToNull(component.getDescription()))
return ComponentImpl.builder(Component.Type.MODULE)
.setUuid(uuidSupplier.apply(moduleKey))
.setKey(moduleKey)
+ .setPublicKey(publicKeyGenerator.generateKey(component, null))
.setName(nameOfOthers(component, moduleKey))
.setStatus(convertStatus(component.getStatus()))
.setDescription(trimToNull(component.getDescription()))
return ComponentImpl.builder(convertDirOrFileType(component.getType()))
.setUuid(uuidSupplier.apply(key))
.setKey(key)
+ .setPublicKey(publicKeyGenerator.generateKey(closestModule, component))
.setName(nameOfOthers(component, key))
.setStatus(convertStatus(component.getStatus()))
.setDescription(trimToNull(component.getDescription()))
import java.util.stream.Stream;
import javax.annotation.CheckForNull;
import javax.annotation.Nullable;
-import org.sonar.core.component.ComponentKeys;
import org.sonar.db.DbClient;
import org.sonar.db.DbSession;
import org.sonar.db.component.SnapshotDto;
import org.sonar.db.component.SnapshotQuery;
import org.sonar.scanner.protocol.output.ScannerReport;
import org.sonar.server.computation.task.projectanalysis.analysis.Analysis;
+import org.sonar.server.computation.task.projectanalysis.analysis.Branch;
import org.sonar.server.computation.task.projectanalysis.analysis.MutableAnalysisMetadataHolder;
import org.sonar.server.computation.task.projectanalysis.batch.BatchReportReader;
import org.sonar.server.computation.task.projectanalysis.component.Component;
import org.sonar.server.computation.task.projectanalysis.component.ComponentKeyGenerator;
import org.sonar.server.computation.task.projectanalysis.component.ComponentTreeBuilder;
import org.sonar.server.computation.task.projectanalysis.component.ComponentUuidFactory;
+import org.sonar.server.computation.task.projectanalysis.component.DefaultBranchImpl;
import org.sonar.server.computation.task.projectanalysis.component.MutableTreeRootHolder;
import org.sonar.server.computation.task.step.ComputationStep;
-import static org.apache.commons.lang.StringUtils.isEmpty;
-import static org.apache.commons.lang.StringUtils.trimToNull;
-
/**
* Populates the {@link MutableTreeRootHolder} and {@link MutableAnalysisMetadataHolder} from the {@link BatchReportReader}
*/
try (DbSession dbSession = dbClient.openSession(false)) {
ScannerReport.Component reportProject = reportReader.readComponent(analysisMetadataHolder.getRootComponentRef());
ComponentKeyGenerator keyGenerator = loadKeyGenerator();
+ ComponentKeyGenerator publicKeyGenerator = loadPublicKeyGenerator();
// root key of branch, not necessarily of project
String rootKey = keyGenerator.generateKey(reportProject, null);
String rootUuid = componentUuidFactory.getOrCreateForKey(rootKey);
SnapshotDto baseAnalysis = loadBaseAnalysis(dbSession, rootUuid);
- ComponentTreeBuilder builder = new ComponentTreeBuilder(keyGenerator,
+ ComponentTreeBuilder builder = new ComponentTreeBuilder(keyGenerator, publicKeyGenerator,
componentUuidFactory::getOrCreateForKey,
reportReader::readComponent,
analysisMetadataHolder.getProject(),
}
private ComponentKeyGenerator loadKeyGenerator() {
- return Stream.of(analysisMetadataHolder.getBranch(), Optional.of(new DefaultKeyGenerator()))
+ return Stream.of(analysisMetadataHolder.getBranch(), Optional.of(new DefaultBranchImpl()))
// TODO pull request generator will be added here
.filter(Optional::isPresent)
.flatMap(x -> x.map(Stream::of).orElseGet(Stream::empty))
.get();
}
+ private ComponentKeyGenerator loadPublicKeyGenerator() {
+ Optional<Branch> branch = analysisMetadataHolder.getBranch();
+ if (!branch.isPresent()) {
+ // Used for pull request
+ return new DefaultBranchImpl();
+ }
+ return branch.filter(Branch::isLegacyFeature)
+ .map(b -> new DefaultBranchImpl(b.getName().orElse(null)))
+ .orElseGet(DefaultBranchImpl::new);
+ }
+
@CheckForNull
private SnapshotDto loadBaseAnalysis(DbSession dbSession, String rootUuid) {
return dbClient.snapshotDao().selectAnalysisByQuery(
return null;
}
- private static class DefaultKeyGenerator implements ComponentKeyGenerator {
- @Override
- public String generateKey(ScannerReport.Component module, @Nullable ScannerReport.Component fileOrDir) {
- String moduleKey = module.getKey();
- if (fileOrDir == null || isEmpty(fileOrDir.getPath())) {
- return moduleKey;
- }
- return ComponentKeys.createEffectiveKey(moduleKey, trimToNull(fileOrDir.getPath()));
- }
- }
}
import static com.google.common.base.Preconditions.checkArgument;
import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.Assert.fail;
+import static org.sonar.scanner.protocol.output.ScannerReport.Component.newBuilder;
import static org.sonar.scanner.protocol.output.ScannerReport.Component.ComponentType.DIRECTORY;
import static org.sonar.scanner.protocol.output.ScannerReport.Component.ComponentType.FILE;
import static org.sonar.scanner.protocol.output.ScannerReport.Component.ComponentType.MODULE;
import static org.sonar.scanner.protocol.output.ScannerReport.Component.ComponentType.PROJECT;
import static org.sonar.scanner.protocol.output.ScannerReport.Component.ComponentType.UNRECOGNIZED;
-import static org.sonar.scanner.protocol.output.ScannerReport.Component.newBuilder;
import static org.sonar.server.computation.task.projectanalysis.component.ComponentVisitor.Order.PRE_ORDER;
public class ComponentTreeBuilderTest {
private static final ComponentKeyGenerator KEY_GENERATOR = (module, component) -> "generated_"
+ ComponentKeys.createEffectiveKey(module.getKey(), component != null ? component.getPath() : null);
+ private static final ComponentKeyGenerator PUBLIC_KEY_GENERATOR = (module, component) -> "public_"
+ + ComponentKeys.createEffectiveKey(module.getKey(), component != null ? component.getPath() : null);
private static final Function<String, String> UUID_SUPPLIER = (componentKey) -> componentKey + "_uuid";
private static final EnumSet<ScannerReport.Component.ComponentType> REPORT_TYPES = EnumSet.of(PROJECT, MODULE, DIRECTORY, FILE);
assertThat(root.getUuid()).isEqualTo("generated_K1_uuid");
assertThat(root.getKey()).isEqualTo("generated_K1");
+ assertThat(root.getPublicKey()).isEqualTo("public_K1");
assertThat(root.getType()).isEqualTo(Component.Type.PROJECT);
assertThat(root.getName()).isEqualTo(nameInReport);
assertThat(root.getDescription()).isEqualTo(descriptionInReport);
Component root = call(project);
assertThat(root.getKey()).isEqualTo("generated_" + projectInDb.getKey());
+ assertThat(root.getPublicKey()).isEqualTo("public_" + projectInDb.getKey());
assertThat(root.getChildren()).hasSize(1);
Component module = root.getChildren().iterator().next();
assertThat(module.getKey()).isEqualTo("generated_M");
+ assertThat(module.getPublicKey()).isEqualTo("public_M");
assertThat(module.getChildren()).hasSize(1);
Component directory = module.getChildren().iterator().next();
assertThat(directory.getKey()).isEqualTo("generated_M:src/js");
+ assertThat(directory.getPublicKey()).isEqualTo("public_M:src/js");
assertThat(directory.getChildren()).hasSize(1);
Component file = directory.getChildren().iterator().next();
assertThat(file.getKey()).isEqualTo("generated_M:src/js/Foo.js");
+ assertThat(file.getPublicKey()).isEqualTo("public_M:src/js/Foo.js");
assertThat(file.getChildren()).isEmpty();
}
@Test
- public void names_of_module_directory_and_file_are_keys_if_names_are_absent_from_report() {
+ public void names_of_module_directory_and_file_are_public_keys_if_names_are_absent_from_report() {
ScannerReport.Component project = newBuilder()
.setType(PROJECT)
.setKey(projectInDb.getKey())
}
@Test
- public void name_of_module_directory_and_files_includes_name_of_closest_module() {
+ public void keys_of_module_directory_and_files_includes_name_of_closest_module() {
ScannerReport.Component project = newBuilder()
.setType(PROJECT)
.setKey("project 1")
Component root = call(project);
Map<Integer, Component> componentsByRef = indexComponentByRef(root);
assertThat(componentsByRef.get(11).getKey()).isEqualTo("generated_module 1");
+ assertThat(componentsByRef.get(11).getPublicKey()).isEqualTo("public_module 1");
assertThat(componentsByRef.get(12).getKey()).isEqualTo("generated_module 2");
+ assertThat(componentsByRef.get(12).getPublicKey()).isEqualTo("public_module 2");
assertThat(componentsByRef.get(13).getKey()).isEqualTo("generated_module 3");
+ assertThat(componentsByRef.get(13).getPublicKey()).isEqualTo("public_module 3");
assertThat(componentsByRef.get(21).getKey()).startsWith("generated_project 1:");
+ assertThat(componentsByRef.get(21).getPublicKey()).startsWith("public_project 1:");
assertThat(componentsByRef.get(22).getKey()).startsWith("generated_module 1:");
+ assertThat(componentsByRef.get(22).getPublicKey()).startsWith("public_module 1:");
assertThat(componentsByRef.get(23).getKey()).startsWith("generated_module 2:");
+ assertThat(componentsByRef.get(23).getPublicKey()).startsWith("public_module 2:");
assertThat(componentsByRef.get(24).getKey()).startsWith("generated_module 3:");
+ assertThat(componentsByRef.get(24).getPublicKey()).startsWith("public_module 3:");
assertThat(componentsByRef.get(31).getKey()).startsWith("generated_project 1:");
+ assertThat(componentsByRef.get(31).getPublicKey()).startsWith("public_project 1:");
assertThat(componentsByRef.get(32).getKey()).startsWith("generated_module 1:");
+ assertThat(componentsByRef.get(32).getPublicKey()).startsWith("public_module 1:");
assertThat(componentsByRef.get(33).getKey()).startsWith("generated_module 2:");
+ assertThat(componentsByRef.get(33).getPublicKey()).startsWith("public_module 2:");
assertThat(componentsByRef.get(34).getKey()).startsWith("generated_module 3:");
+ assertThat(componentsByRef.get(34).getPublicKey()).startsWith("public_module 3:");
assertThat(componentsByRef.get(35).getKey()).startsWith("generated_project 1:");
+ assertThat(componentsByRef.get(35).getPublicKey()).startsWith("public_project 1:");
assertThat(componentsByRef.get(36).getKey()).startsWith("generated_module 1:");
+ assertThat(componentsByRef.get(36).getPublicKey()).startsWith("public_module 1:");
assertThat(componentsByRef.get(37).getKey()).startsWith("generated_module 2:");
+ assertThat(componentsByRef.get(37).getPublicKey()).startsWith("public_module 2:");
assertThat(componentsByRef.get(38).getKey()).startsWith("generated_module 3:");
+ assertThat(componentsByRef.get(38).getPublicKey()).startsWith("public_module 3:");
}
@Test
}
private ComponentTreeBuilder newUnderTest(@Nullable SnapshotDto baseAnalysis) {
- return new ComponentTreeBuilder(KEY_GENERATOR, UUID_SUPPLIER, scannerComponentProvider, projectInDb, baseAnalysis);
+ return new ComponentTreeBuilder(KEY_GENERATOR, PUBLIC_KEY_GENERATOR, UUID_SUPPLIER, scannerComponentProvider, projectInDb, baseAnalysis);
}
private static Map<Integer, Component> indexComponentByRef(Component root) {
import com.google.common.collect.ImmutableList;
import java.util.ArrayList;
import java.util.List;
-import java.util.Objects;
import javax.annotation.CheckForNull;
import javax.annotation.Nullable;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkState;
import static java.util.Arrays.asList;
+import static java.util.Objects.requireNonNull;
/**
* Implementation of {@link Component} to unit test report components.
@CheckForNull
private final String description;
private final String key;
+ private final String publicKey;
private final String uuid;
private final ReportAttributes reportAttributes;
private final FileAttributes fileAttributes;
this.type = builder.type;
this.status = builder.status;
this.key = builder.key;
+ this.publicKey = builder.publicKey;
this.name = builder.name == null ? String.valueOf(builder.key) : builder.name;
this.description = builder.description;
this.uuid = builder.uuid;
return key;
}
+ @Override
+ public String getPublicKey() {
+ if (publicKey == null) {
+ throw new UnsupportedOperationException(String.format("Component key of ref '%d' has not be fed yet", this.reportAttributes.getRef()));
+ }
+ return publicKey;
+ }
+
@Override
public String getName() {
return this.name;
private Status status;
private String uuid;
private String key;
+ private String publicKey;
private String name;
private String version;
private String description;
}
public Builder setStatus(Status s) {
- this.status = Objects.requireNonNull(s);
+ this.status = requireNonNull(s);
return this;
}
public Builder setUuid(String s) {
- this.uuid = Objects.requireNonNull(s);
+ this.uuid = requireNonNull(s);
return this;
}
}
public Builder setKey(String s) {
- this.key = Objects.requireNonNull(s);
+ this.key = requireNonNull(s);
+ return this;
+ }
+
+ public Builder setPublicKey(String publicKey) {
+ this.publicKey = requireNonNull(publicKey);
return this;
}
return key;
}
+ /**
+ * Views has no branch feature, the public key is the same as the key
+ */
+ @Override
+ public String getPublicKey() {
+ return getKey();
+ }
+
@Override
public String getName() {
checkState(this.name != null, "No name has been set");
import com.tngtech.java.junit.dataprovider.UseDataProvider;
import java.util.HashMap;
import java.util.Map;
+import java.util.Optional;
import javax.annotation.Nullable;
import org.junit.Rule;
import org.junit.Test;
import org.sonar.scanner.protocol.output.ScannerReport;
import org.sonar.scanner.protocol.output.ScannerReport.Component.ComponentType;
import org.sonar.scanner.protocol.output.ScannerReport.Component.FileStatus;
+import org.sonar.server.computation.task.projectanalysis.analysis.Branch;
import org.sonar.server.computation.task.projectanalysis.analysis.MutableAnalysisMetadataHolderRule;
import org.sonar.server.computation.task.projectanalysis.analysis.Project;
import org.sonar.server.computation.task.projectanalysis.batch.BatchReportReaderRule;
import org.sonar.server.computation.task.projectanalysis.component.Component;
+import org.sonar.server.computation.task.projectanalysis.component.DefaultBranchImpl;
import org.sonar.server.computation.task.projectanalysis.component.MutableTreeRootHolderRule;
import static com.google.common.base.Predicates.in;
import static com.google.common.collect.FluentIterable.from;
import static java.util.Arrays.asList;
import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
import static org.sonar.db.component.ComponentTesting.newDirectory;
import static org.sonar.db.component.ComponentTesting.newFileDto;
import static org.sonar.db.component.ComponentTesting.newModuleDto;
@Rule
public DbTester dbTester = DbTester.create(System2.INSTANCE);
@Rule
- public BatchReportReaderRule reportReader = new BatchReportReaderRule();
+ public BatchReportReaderRule reportReader = new BatchReportReaderRule()
+ .setMetadata(ScannerReport.Metadata.newBuilder()
+ .setProjectKey(REPORT_PROJECT_KEY)
+ .setRootComponentRef(ROOT_REF)
+ .build());
@Rule
public MutableTreeRootHolderRule treeRootHolder = new MutableTreeRootHolderRule();
@Rule
- public MutableAnalysisMetadataHolderRule analysisMetadataHolder = new MutableAnalysisMetadataHolderRule()
- .setRootComponentRef(ROOT_REF)
- .setAnalysisDate(ANALYSIS_DATE)
- .setBranch(null)
- .setProject(new Project("U1", REPORT_PROJECT_KEY, REPORT_PROJECT_KEY));
+ public MutableAnalysisMetadataHolderRule analysisMetadataHolder = new MutableAnalysisMetadataHolderRule();
private DbClient dbClient = dbTester.getDbClient();
private BuildComponentTreeStep underTest = new BuildComponentTreeStep(dbClient, reportReader, treeRootHolder, analysisMetadataHolder);
@Test(expected = NullPointerException.class)
public void fails_if_root_component_does_not_exist_in_reportReader() {
+ setAnalysisMetadataHolder();
+
underTest.execute();
}
@Test
@UseDataProvider("allComponentTypes")
public void verify_ref_and_type(ComponentType componentType) {
+ setAnalysisMetadataHolder();
int componentRef = 1;
reportReader.putComponent(component(componentRef, componentType));
@Test
public void verify_tree_is_correctly_built() {
+ setAnalysisMetadataHolder();
reportReader.putComponent(component(ROOT_REF, PROJECT, MODULE_REF));
reportReader.putComponent(component(MODULE_REF, MODULE, DIR_REF_1, DIR_REF_2));
reportReader.putComponent(component(DIR_REF_1, DIRECTORY, FILE_1_REF, FILE_2_REF));
@Test
public void compute_keys_and_uuids() {
+ setAnalysisMetadataHolder();
reportReader.putComponent(componentWithKey(ROOT_REF, PROJECT, REPORT_PROJECT_KEY, MODULE_REF));
reportReader.putComponent(componentWithKey(MODULE_REF, MODULE, REPORT_MODULE_KEY, DIR_REF_1));
reportReader.putComponent(componentWithPath(DIR_REF_1, DIRECTORY, REPORT_DIR_KEY_1, FILE_1_REF));
@Test
public void return_existing_uuids() {
+ setAnalysisMetadataHolder();
OrganizationDto organizationDto = dbTester.organizations().insert();
ComponentDto project = insertComponent(newPrivateProjectDto(organizationDto, "ABCD").setDbKey(REPORT_PROJECT_KEY));
ComponentDto module = insertComponent(newModuleDto("BCDE", project).setDbKey(REPORT_MODULE_KEY));
verifyComponent(FILE_1_REF, REPORT_MODULE_KEY + ":" + REPORT_FILE_KEY_1, "DEFG");
}
-// @Test
-// public void use_branch_to_generate_keys() {
-// MutableAnalysisMetadataHolder analysisMetadataHolder = new AnalysisMetadataHolderImpl()
-// .setRootComponentRef(ROOT_REF)
-// .setAnalysisDate(ANALYSIS_DATE)
-// .setBranch("origin/master");
-//
-// BuildComponentTreeStep underTest = new BuildComponentTreeStep(dbClient, reportReader, treeRootHolder, analysisMetadataHolder);
-//
-// reportReader.putComponent(componentWithKey(ROOT_REF, PROJECT, REPORT_PROJECT_KEY, MODULE_REF));
-// reportReader.putComponent(componentWithKey(MODULE_REF, MODULE, REPORT_MODULE_KEY, DIR_REF_1));
-// reportReader.putComponent(componentWithPath(DIR_REF_1, DIRECTORY, REPORT_DIR_KEY_1, FILE_1_REF));
-// reportReader.putComponent(componentWithPath(FILE_1_REF, FILE, REPORT_FILE_KEY_1));
-//
-// underTest.execute();
-//
-// verifyComponent(ROOT_REF, REPORT_PROJECT_KEY + ":origin/master");
-// verifyComponent(MODULE_REF, REPORT_MODULE_KEY + ":origin/master");
-// verifyComponent(DIR_REF_1, REPORT_MODULE_KEY + ":origin/master:" + REPORT_DIR_KEY_1);
-// verifyComponent(FILE_1_REF, REPORT_MODULE_KEY + ":origin/master:" + REPORT_FILE_KEY_1);
-// }
+ @Test
+ public void generate_keys_when_using_branch() {
+ Branch branch = mock(Branch.class);
+ when(branch.getName()).thenReturn(Optional.of("origin/feature"));
+ when(branch.isMain()).thenReturn(false);
+ when(branch.isLegacyFeature()).thenReturn(false);
+ when(branch.generateKey(any(ScannerReport.Component.class), any(ScannerReport.Component.class))).thenReturn("generated");
+ analysisMetadataHolder.setRootComponentRef(ROOT_REF)
+ .setAnalysisDate(ANALYSIS_DATE)
+ .setProject(new Project("U1", REPORT_PROJECT_KEY, REPORT_PROJECT_KEY))
+ .setBranch(branch);
+ BuildComponentTreeStep underTest = new BuildComponentTreeStep(dbClient, reportReader, treeRootHolder, analysisMetadataHolder);
+ reportReader.putComponent(componentWithKey(ROOT_REF, PROJECT, REPORT_PROJECT_KEY, MODULE_REF));
+ reportReader.putComponent(componentWithKey(MODULE_REF, MODULE, REPORT_MODULE_KEY, DIR_REF_1));
+ reportReader.putComponent(componentWithPath(DIR_REF_1, DIRECTORY, REPORT_DIR_KEY_1, FILE_1_REF));
+ reportReader.putComponent(componentWithPath(FILE_1_REF, FILE, REPORT_FILE_KEY_1));
+
+ underTest.execute();
+
+ verifyComponent(ROOT_REF, "generated", REPORT_PROJECT_KEY, null);
+ verifyComponent(MODULE_REF, "generated", REPORT_MODULE_KEY, null);
+ verifyComponent(DIR_REF_1, "generated", REPORT_MODULE_KEY + ":" + REPORT_DIR_KEY_1, null);
+ verifyComponent(FILE_1_REF, "generated", REPORT_MODULE_KEY + ":" + REPORT_FILE_KEY_1, null);
+ }
+
+ @Test
+ public void generate_keys_when_using_main_branch() {
+ Branch branch = mock(Branch.class);
+ when(branch.getName()).thenReturn(Optional.of("origin/master"));
+ when(branch.isMain()).thenReturn(true);
+ when(branch.isLegacyFeature()).thenReturn(false);
+ when(branch.generateKey(any(ScannerReport.Component.class), any(ScannerReport.Component.class))).thenReturn("generated");
+ analysisMetadataHolder.setRootComponentRef(ROOT_REF)
+ .setAnalysisDate(ANALYSIS_DATE)
+ .setProject(new Project("U1", REPORT_PROJECT_KEY, REPORT_PROJECT_KEY))
+ .setBranch(branch);
+ BuildComponentTreeStep underTest = new BuildComponentTreeStep(dbClient, reportReader, treeRootHolder, analysisMetadataHolder);
+ reportReader.putComponent(componentWithKey(ROOT_REF, PROJECT, REPORT_PROJECT_KEY, MODULE_REF));
+ reportReader.putComponent(componentWithKey(MODULE_REF, MODULE, REPORT_MODULE_KEY, DIR_REF_1));
+ reportReader.putComponent(componentWithPath(DIR_REF_1, DIRECTORY, REPORT_DIR_KEY_1, FILE_1_REF));
+ reportReader.putComponent(componentWithPath(FILE_1_REF, FILE, REPORT_FILE_KEY_1));
+
+ underTest.execute();
+
+ verifyComponent(ROOT_REF, "generated", REPORT_PROJECT_KEY, null);
+ verifyComponent(MODULE_REF, "generated", REPORT_MODULE_KEY, null);
+ verifyComponent(DIR_REF_1, "generated", REPORT_MODULE_KEY + ":" + REPORT_DIR_KEY_1, null);
+ verifyComponent(FILE_1_REF, "generated", REPORT_MODULE_KEY + ":" + REPORT_FILE_KEY_1, null);
+ }
+
+ @Test
+ public void generate_keys_when_using_legacy_branch() {
+ analysisMetadataHolder.setRootComponentRef(ROOT_REF)
+ .setAnalysisDate(ANALYSIS_DATE)
+ .setProject(new Project("U1", REPORT_PROJECT_KEY, REPORT_PROJECT_KEY))
+ .setBranch(new DefaultBranchImpl("origin/feature"));
+ BuildComponentTreeStep underTest = new BuildComponentTreeStep(dbClient, reportReader, treeRootHolder, analysisMetadataHolder);
+ reportReader.putComponent(componentWithKey(ROOT_REF, PROJECT, REPORT_PROJECT_KEY, MODULE_REF));
+ reportReader.putComponent(componentWithKey(MODULE_REF, MODULE, REPORT_MODULE_KEY, DIR_REF_1));
+ reportReader.putComponent(componentWithPath(DIR_REF_1, DIRECTORY, REPORT_DIR_KEY_1, FILE_1_REF));
+ reportReader.putComponent(componentWithPath(FILE_1_REF, FILE, REPORT_FILE_KEY_1));
+
+ underTest.execute();
+
+ verifyComponent(ROOT_REF, REPORT_PROJECT_KEY + ":origin/feature", null);
+ verifyComponent(MODULE_REF, REPORT_MODULE_KEY + ":origin/feature", null);
+ verifyComponent(DIR_REF_1, REPORT_MODULE_KEY + ":origin/feature:" + REPORT_DIR_KEY_1, null);
+ verifyComponent(FILE_1_REF, REPORT_MODULE_KEY + ":origin/feature:" + REPORT_FILE_KEY_1, null);
+ }
+
+ @Test
+ public void compute_keys_when_no_branch() {
+ analysisMetadataHolder.setRootComponentRef(ROOT_REF)
+ .setAnalysisDate(ANALYSIS_DATE)
+ .setProject(new Project("U1", REPORT_PROJECT_KEY, REPORT_PROJECT_KEY))
+ .setBranch(null);
+ BuildComponentTreeStep underTest = new BuildComponentTreeStep(dbClient, reportReader, treeRootHolder, analysisMetadataHolder);
+ reportReader.putComponent(componentWithKey(ROOT_REF, PROJECT, REPORT_PROJECT_KEY, MODULE_REF));
+ reportReader.putComponent(componentWithKey(MODULE_REF, MODULE, REPORT_MODULE_KEY, DIR_REF_1));
+ reportReader.putComponent(componentWithPath(DIR_REF_1, DIRECTORY, REPORT_DIR_KEY_1, FILE_1_REF));
+ reportReader.putComponent(componentWithPath(FILE_1_REF, FILE, REPORT_FILE_KEY_1));
+
+ underTest.execute();
+
+ verifyComponent(ROOT_REF, REPORT_PROJECT_KEY);
+ verifyComponent(MODULE_REF, REPORT_MODULE_KEY);
+ verifyComponent(DIR_REF_1, REPORT_MODULE_KEY + ":" + REPORT_DIR_KEY_1);
+ verifyComponent(FILE_1_REF, REPORT_MODULE_KEY + ":" + REPORT_FILE_KEY_1);
+ }
@Test
public void compute_keys_and_uuids_on_project_having_module_and_directory() {
+ setAnalysisMetadataHolder();
reportReader.putComponent(componentWithKey(ROOT_REF, PROJECT, REPORT_PROJECT_KEY, MODULE_REF, DIR_REF_2));
reportReader.putComponent(componentWithKey(MODULE_REF, MODULE, REPORT_MODULE_KEY, DIR_REF_1));
reportReader.putComponent(componentWithPath(DIR_REF_1, DIRECTORY, REPORT_DIR_KEY_1, FILE_1_REF));
@Test
public void compute_keys_and_uuids_on_multi_modules() {
+ setAnalysisMetadataHolder();
reportReader.putComponent(componentWithKey(ROOT_REF, PROJECT, REPORT_PROJECT_KEY, MODULE_REF));
reportReader.putComponent(componentWithKey(MODULE_REF, MODULE, REPORT_MODULE_KEY, 100));
reportReader.putComponent(componentWithKey(100, MODULE, "SUB_MODULE_KEY", DIR_REF_1));
@Test
public void return_existing_uuids_when_components_were_removed() {
+ setAnalysisMetadataHolder();
OrganizationDto organizationDto = dbTester.organizations().insert();
ComponentDto project = insertComponent(newPrivateProjectDto(organizationDto, "ABCD").setDbKey(REPORT_PROJECT_KEY));
ComponentDto removedModule = insertComponent(newModuleDto("BCDE", project).setDbKey(REPORT_MODULE_KEY).setEnabled(false));
@Test
public void set_no_base_project_snapshot_when_no_snapshot() throws Exception {
+ setAnalysisMetadataHolder();
reportReader.putComponent(componentWithKey(ROOT_REF, PROJECT, REPORT_PROJECT_KEY));
underTest.execute();
@Test
public void set_no_base_project_snapshot_when_no_last_snapshot() throws Exception {
+ setAnalysisMetadataHolder();
OrganizationDto organizationDto = dbTester.organizations().insert();
ComponentDto project = insertComponent(newPrivateProjectDto(organizationDto, "ABCD").setDbKey(REPORT_PROJECT_KEY));
insertSnapshot(newAnalysis(project).setLast(false));
@Test
public void set_base_project_snapshot_when_last_snapshot_exist() throws Exception {
+ setAnalysisMetadataHolder();
OrganizationDto organizationDto = dbTester.organizations().insert();
ComponentDto project = insertComponent(newPrivateProjectDto(organizationDto, "ABCD").setDbKey(REPORT_PROJECT_KEY));
insertSnapshot(newAnalysis(project).setLast(true));
}
private void verifyComponent(int ref, String key) {
- verifyComponent(ref, key, null);
+ verifyComponent(ref, key, key, null);
}
private void verifyComponent(int ref, String key, @Nullable String uuid) {
+ verifyComponent(ref, key, key, uuid);
+ }
+
+ private void verifyComponent(int ref, String key, String publicKey, @Nullable String uuid) {
Map<Integer, Component> componentsByRef = indexAllComponentsInTreeByRef(treeRootHolder.getRoot());
Component component = componentsByRef.get(ref);
assertThat(component.getKey()).isEqualTo(key);
+ assertThat(component.getPublicKey()).isEqualTo(publicKey);
if (uuid != null) {
assertThat(component.getUuid()).isEqualTo(uuid);
} else {
return snapshot;
}
+ private void setAnalysisMetadataHolder() {
+ analysisMetadataHolder.setRootComponentRef(ROOT_REF)
+ .setAnalysisDate(ANALYSIS_DATE)
+ .setBranch(new DefaultBranchImpl(null))
+ .setProject(new Project("U1", REPORT_PROJECT_KEY, REPORT_PROJECT_KEY));
+ }
+
}