Skip to content

Commit

Permalink
Merge a98bbc6 into 8a6725a
Browse files Browse the repository at this point in the history
  • Loading branch information
stevebillings committed Oct 30, 2019
2 parents 8a6725a + a98bbc6 commit f0072ec
Show file tree
Hide file tree
Showing 12 changed files with 120 additions and 20 deletions.
Expand Up @@ -147,6 +147,10 @@ public enum DetectProperty {
@HelpDescription("The Bazel target (for example, //foo:foolib) for which dependencies are collected. For Detect to run Bazel, this property must be set.")
DETECT_BAZEL_TARGET("detect.bazel.target", "Bazel Target", "5.2.0", PropertyType.STRING, PropertyAuthority.NONE),

@HelpGroup(primary = GROUP_BAZEL, additional = GROUP_SOURCE_SCAN)
@HelpDescription("A comma-separated list of additional options to pass to the bazel cquery command.")
DETECT_BAZEL_CQUERY_OPTIONS("detect.bazel.cquery.options", "Bazel cquery additional options", "6.1.0", PropertyType.STRING, PropertyAuthority.NONE),

@HelpGroup(primary = GROUP_BAZEL, additional = GROUP_SOURCE_SCAN)
@HelpDescription("The Bazel workspace rule used to pull in external dependencies. If not set, Detect will attempt to determine the rule from the contents of the WORKSPACE file.")
@AcceptableValues(value = { "maven_jar", "maven_install", "UNSPECIFIED" }, caseSensitive = true, strict = true)
Expand Down
Expand Up @@ -82,7 +82,8 @@ public DetectableResult extractable() throws DetectableException {
@Override
public Extraction extract(final ExtractionEnvironment extractionEnvironment) {
final BazelProjectNameGenerator projectNameGenerator = new BazelProjectNameGenerator();
final Extraction extractResult = bazelExtractor.extract(bazelExe, environment.getDirectory(), bazelWorkspace, bazelDetectableOptions.getTargetName(), projectNameGenerator, bazelDetectableOptions.getBazelDependencyRule());
final Extraction extractResult = bazelExtractor.extract(bazelExe, environment.getDirectory(), bazelWorkspace, bazelDetectableOptions.getTargetName(), projectNameGenerator, bazelDetectableOptions.getBazelDependencyRule(),
bazelDetectableOptions.getBazelCqueryAdditionalOptions());
return extractResult;
}
}
Expand Up @@ -22,12 +22,17 @@
*/
package com.synopsys.integration.detectable.detectables.bazel;

import java.util.List;

public class BazelDetectableOptions {
private final String targetName;
private final String bazelDependencyRule;
public BazelDetectableOptions(final String targetName, final String bazelDependencyRule) {
private final List<String> bazelCqueryAdditionalOptions;
public BazelDetectableOptions(final String targetName, final String bazelDependencyRule,
final List<String> bazelCqueryAdditionalOptions) {
this.targetName = targetName;
this.bazelDependencyRule = bazelDependencyRule;
this.bazelCqueryAdditionalOptions = bazelCqueryAdditionalOptions;
}

public String getTargetName() {
Expand All @@ -37,4 +42,8 @@ public String getTargetName() {
public String getBazelDependencyRule() {
return bazelDependencyRule;
}

public List<String> getBazelCqueryAdditionalOptions() {
return bazelCqueryAdditionalOptions;
}
}
Expand Up @@ -57,12 +57,13 @@ public BazelExtractor(final ExecutableRunner executableRunner,
}

public Extraction extract(final File bazelExe, final File workspaceDir, final BazelWorkspace bazelWorkspace, final String bazelTarget,
final BazelProjectNameGenerator bazelProjectNameGenerator, final String providedBazelDependencyType) {
final BazelProjectNameGenerator bazelProjectNameGenerator, final String providedBazelDependencyType,
final List<String> providedCqueryAdditionalOptions) {
logger.debug("Bazel extraction:");
try {
final WorkspaceRule ruleFromWorkspaceFile = bazelWorkspace.getDependencyRule();
final BazelCommandExecutor bazelCommandExecutor = new BazelCommandExecutor(executableRunner, workspaceDir, bazelExe);
final BazelVariableSubstitutor bazelVariableSubstitutor = new BazelVariableSubstitutor(bazelTarget);
final BazelVariableSubstitutor bazelVariableSubstitutor = new BazelVariableSubstitutor(bazelTarget, providedCqueryAdditionalOptions);
final Pipelines pipelines = new Pipelines(bazelCommandExecutor, bazelVariableSubstitutor);
final WorkspaceRule workspaceRule = workspaceRuleChooser.choose(ruleFromWorkspaceFile, providedBazelDependencyType);
final List<StepExecutor> pipeline = pipelines.get(workspaceRule);
Expand Down
Expand Up @@ -54,7 +54,7 @@ public Pipelines(final BazelCommandExecutor bazelCommandExecutor, final BazelVar
availablePipelines.put(WorkspaceRule.MAVEN_JAR, mavenJarPipeline);

final List<StepExecutor> mavenInstallPipeline = new ArrayList<>();
mavenInstallPipeline.add(new StepExecutorExecuteBazelOnEach(bazelCommandExecutor, bazelVariableSubstitutor, Arrays.asList("cquery", "--noimplicit_deps", "kind(j.*import, deps(${detect.bazel.target}))", "--output", "build")));
mavenInstallPipeline.add(new StepExecutorExecuteBazelOnEach(bazelCommandExecutor, bazelVariableSubstitutor, Arrays.asList("cquery", "--noimplicit_deps", "${detect.bazel.cquery.options}", "kind(j.*import, deps(${detect.bazel.target}))", "--output", "build")));
mavenInstallPipeline.add(new StepExecutorSplitEach("\n"));
mavenInstallPipeline.add(new StepExecutorFilter(".*maven_coordinates=.*"));
mavenInstallPipeline.add(new StepExecutorReplaceInEach("^\\s*tags\\s*\\s*=\\s*\\[\\s*\"maven_coordinates=", ""));
Expand Down
Expand Up @@ -28,28 +28,59 @@
import java.util.Map;

public class BazelVariableSubstitutor {
private final Map<String, String> substitutions;
private final Map<String, String> stringSubstitutions;
private final Map<String, List<String>> listInsertions;

public BazelVariableSubstitutor(final String bazelTarget) {
substitutions = new HashMap<>(1);
substitutions.put("\\$\\{detect.bazel.target}", bazelTarget);
public BazelVariableSubstitutor(final String bazelTarget, final List<String> cqueryAdditionalOptions) {
// the keys are regex's, requiring regex special character escaping
stringSubstitutions = new HashMap<>(1);
stringSubstitutions.put("\\$\\{detect.bazel.target}", bazelTarget);

// the keys are plain strings
listInsertions = new HashMap<>(1);
listInsertions.put("${detect.bazel.cquery.options}", cqueryAdditionalOptions);
}

public List<String> substitute(final List<String> origStrings, final String input) {
final List<String> modifiedStrings = new ArrayList<>(origStrings.size());
for (String origString : origStrings) {
modifiedStrings.add(substitute(origString, input));
boolean foundListInsertionPlaceholder = handleListInsertion(modifiedStrings, origString, input);
if (!foundListInsertionPlaceholder) {
handleStringSubstitutions(input, modifiedStrings, origString);
}
}
return modifiedStrings;
}

private void handleStringSubstitutions(final String input, final List<String> modifiedStrings, final String origString) {
modifiedStrings.add(substitute(origString, input));
}

private boolean handleListInsertion(final List<String> modifiedStrings, final String origString, final String input) {
boolean foundListInsertionVariable = false;
for (final String listInsertionKey : listInsertions.keySet()) {
if (origString.equals(listInsertionKey)) {
foundListInsertionVariable = true;
final List<String> valuesToInsert = listInsertions.get(listInsertionKey);
if (valuesToInsert != null) {
for (final String valueToInsert : valuesToInsert) {
// Substituting here gives user the ability to use ${detect.bazel.target} and ${input.item} in list insertion values
handleStringSubstitutions(input, modifiedStrings, valueToInsert);
}
}
break; // it'll only match one
}
}
return foundListInsertionVariable;
}

private String substitute(final String origString, final String input) {
String modifiedString = origString;
if (input != null) {
substitutions.put("\\$\\{input.item}", input);
stringSubstitutions.put("\\$\\{input.item}", input);
}
for (String variablePattern : substitutions.keySet()) {
modifiedString = modifiedString.replaceAll(variablePattern, substitutions.get(variablePattern));
for (final String variablePattern : stringSubstitutions.keySet()) {
modifiedString = modifiedString.replaceAll(variablePattern, stringSubstitutions.get(variablePattern));
}
return modifiedString;
}
Expand Down
Expand Up @@ -94,7 +94,8 @@ public void testMavenJar() throws ExecutableRunnerException, IntegrationExceptio
Mockito.when(bazelCmdExecutableOutputGetDependencyDetailsGuava.getStandardOutput()).thenReturn(guavaXml);
Mockito.when(executableRunner.execute(workspaceDir, bazelExe, bazelArgsGetDependencyDetailsGuava)).thenReturn(bazelCmdExecutableOutputGetDependencyDetailsGuava);

final Extraction result = bazelExtractor.extract(bazelExe, workspaceDir, bazelWorkspace, "//:ProjectRunner", new BazelProjectNameGenerator(), null);
final Extraction result = bazelExtractor.extract(bazelExe, workspaceDir, bazelWorkspace, "//:ProjectRunner", new BazelProjectNameGenerator(), null,
null);

assertEquals(1, result.getCodeLocations().size());
final Set<Dependency> dependencies = result.getCodeLocations().get(0).getDependencyGraph().getRootDependencies();
Expand Down Expand Up @@ -146,7 +147,7 @@ public void testMavenInstall() throws ExecutableRunnerException, IntegrationExce
" tags = [\"maven_coordinates=com.google.errorprone:error_prone_annotations:2.2.0\"],");
Mockito.when(executableRunner.execute(workspaceDir, bazelExe, bazelArgsGetDependencies)).thenReturn(bazelCmdExecutableOutputGetDependencies);

final Extraction result = bazelExtractor.extract(bazelExe, workspaceDir, bazelWorkspace, "//:ProjectRunner", new BazelProjectNameGenerator(), null);
final Extraction result = bazelExtractor.extract(bazelExe, workspaceDir, bazelWorkspace, "//:ProjectRunner", new BazelProjectNameGenerator(), null, null);

assertEquals(1, result.getCodeLocations().size());
final Set<Dependency> dependencies = result.getCodeLocations().get(0).getDependencyGraph().getRootDependencies();
Expand Down
Expand Up @@ -3,6 +3,7 @@
import static org.junit.jupiter.api.Assertions.assertEquals;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import org.junit.jupiter.api.Test;
Expand All @@ -13,7 +14,7 @@ public class BazelVariableSubstitutorTest {

@Test
public void testTargetOnly() {
BazelVariableSubstitutor substitutor = new BazelVariableSubstitutor("//foo:foolib");
BazelVariableSubstitutor substitutor = new BazelVariableSubstitutor("//foo:foolib", new ArrayList<>(0));
final List<String> origArgs = new ArrayList<>();
origArgs.add("query");
origArgs.add("filter(\"@.*:jar\", deps(${detect.bazel.target}))");
Expand All @@ -26,7 +27,7 @@ public void testTargetOnly() {

@Test
public void testInput() {
BazelVariableSubstitutor substitutor = new BazelVariableSubstitutor("//foo:foolib");
BazelVariableSubstitutor substitutor = new BazelVariableSubstitutor("//foo:foolib", null);
final List<String> origArgs = new ArrayList<>();
origArgs.add("query");
origArgs.add("filter(\"@.*:jar\", deps(${detect.bazel.target}))");
Expand All @@ -38,4 +39,23 @@ public void testInput() {
assertEquals("filter(\"@.*:jar\", deps(//foo:foolib))", adjustedArgs.get(1));
assertEquals("kind(maven_jar, //external:org_apache_commons_commons_io)", adjustedArgs.get(2));
}


@Test
public void testListInsertion() {
BazelVariableSubstitutor substitutor = new BazelVariableSubstitutor("//foo:foolib", Arrays.asList("--define=a=b", "--define=c=d"));
final List<String> origArgs = new ArrayList<>();
origArgs.add("cquery");
origArgs.add("${detect.bazel.cquery.options}");
origArgs.add("filter(\"@.*:jar\", deps(${detect.bazel.target}))");
origArgs.add("kind(maven_jar, ${input.item})");

final List<String> adjustedArgs = substitutor.substitute(origArgs, "//external:org_apache_commons_commons_io");
assertEquals(5, adjustedArgs.size());
assertEquals("cquery", adjustedArgs.get(0));
assertEquals("--define=a=b", adjustedArgs.get(1));
assertEquals("--define=c=d", adjustedArgs.get(2));
assertEquals("filter(\"@.*:jar\", deps(//foo:foolib))", adjustedArgs.get(3));
assertEquals("kind(maven_jar, //external:org_apache_commons_commons_io)", adjustedArgs.get(4));
}
}
Expand Up @@ -35,7 +35,7 @@ public void testNoInput() throws ExecutableRunnerException, IntegrationException
Mockito.when(bazelCmdExecutableOutput.getStandardOutput()).thenReturn("@org_apache_commons_commons_io//jar:jar\n@com_google_guava_guava//jar:jar");
Mockito.when(executableRunner.execute(workspaceDir, bazelExe, bazelArgs)).thenReturn(bazelCmdExecutableOutput);
final BazelCommandExecutor bazelCommandExecutor = new BazelCommandExecutor(executableRunner, workspaceDir, bazelExe);
final BazelVariableSubstitutor bazelVariableSubstitutor = new BazelVariableSubstitutor("//:ProjectRunner");
final BazelVariableSubstitutor bazelVariableSubstitutor = new BazelVariableSubstitutor("//:ProjectRunner", null);
final StepExecutor executor = new StepExecutorExecuteBazelOnEach(bazelCommandExecutor, bazelVariableSubstitutor, Arrays.asList("query", "filter(\\\"@.*:jar\\\", deps(${detect.bazel.target}))"));
final List<String> input = new ArrayList<>(0);

Expand Down
Expand Up @@ -24,7 +24,7 @@ public void testApplicable() {
Mockito.when(fileFinder.findFile(new File("."), "WORKSPACE")).thenReturn(new File("src/test/resources/functional/bazel/WORKSPACE"));
final BazelExtractor bazelExtractor = null;
final BazelResolver bazelResolver = null;
final BazelDetectableOptions bazelDetectableOptions = new BazelDetectableOptions("target", "");
final BazelDetectableOptions bazelDetectableOptions = new BazelDetectableOptions("target", "", null);
final BazelDetectable detectable = new BazelDetectable(environment, fileFinder, bazelExtractor, bazelResolver, bazelDetectableOptions);

assertTrue(detectable.applicable().getPassed());
Expand Down
Expand Up @@ -22,6 +22,8 @@
*/
package com.synopsys.integration.detect.configuration;

import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Optional;

Expand Down Expand Up @@ -68,7 +70,16 @@ public DetectableOptionFactory(final DetectConfiguration detectConfiguration, fi
public BazelDetectableOptions createBazelDetectableOptions() {
final String targetName = detectConfiguration.getProperty(DetectProperty.DETECT_BAZEL_TARGET, PropertyAuthority.NONE);
final String bazelDependencyRule = detectConfiguration.getProperty(DetectProperty.DETECT_BAZEL_DEPENDENCY_RULE, PropertyAuthority.NONE);
return new BazelDetectableOptions(targetName, bazelDependencyRule);
final String bazelCqueryAdditionalOptionsString = detectConfiguration.getPropertyValueAsString(DetectProperty.DETECT_BAZEL_CQUERY_OPTIONS, PropertyAuthority.NONE);

final List<String> bazelCqueryAdditionalOptions;
if (StringUtils.isBlank(bazelCqueryAdditionalOptionsString)) {
bazelCqueryAdditionalOptions = null;
} else {
final String[] bazelCqueryAdditionalOptionsArray = bazelCqueryAdditionalOptionsString.split(",");
bazelCqueryAdditionalOptions = Arrays.asList(bazelCqueryAdditionalOptionsArray);
}
return new BazelDetectableOptions(targetName, bazelDependencyRule, bazelCqueryAdditionalOptions);
}

public BitbakeDetectableOptions createBitbakeDetectableOptions() {
Expand Down
@@ -1,3 +1,25 @@
/**
* synopsys-detect
*
* Copyright (c) 2019 Synopsys, Inc.
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package com.synopsys.integration.detect.tool.detector;

import com.synopsys.integration.detect.workflow.event.Event;
Expand Down

0 comments on commit f0072ec

Please sign in to comment.