diff --git a/.gitignore b/.gitignore index 9b39f93..54304bb 100644 --- a/.gitignore +++ b/.gitignore @@ -7,6 +7,7 @@ target/ .project .idea .DS_Store +*.iml # ci config for local ci build .circleci/local-config.yml diff --git a/README.md b/README.md index 7d9cac9..9d7a5e3 100644 --- a/README.md +++ b/README.md @@ -66,14 +66,14 @@ Gradle can be used to build projects developed in various programming languages. ``` plugins { - id 'org.sonatype.gradle.plugins.scan' version '2.8.3' // Update the version as needed + id 'org.sonatype.gradle.plugins.scan' version '3.1.0' // Update the version as needed } ``` - Or `build.gradle.kts`: ``` plugins { - id ("org.sonatype.gradle.plugins.scan") version "2.8.3" // Update the version as needed + id ("org.sonatype.gradle.plugins.scan") version "3.1.0" // Update the version as needed } ``` diff --git a/gradle.properties b/gradle.properties index 50f14d5..9b5022b 100644 --- a/gradle.properties +++ b/gradle.properties @@ -15,5 +15,5 @@ # group=org.sonatype.gradle.plugins -version=3.0.1-SNAPSHOT +version=3.1.0-SNAPSHOT release.useAutomaticVersion=true diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index afba109..9bbc975 100644 Binary files a/gradle/wrapper/gradle-wrapper.jar and b/gradle/wrapper/gradle-wrapper.jar differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 2617362..6514f91 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,7 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.8-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.14-all.zip networkTimeout=10000 +validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew index 65dcd68..faf9300 100755 --- a/gradlew +++ b/gradlew @@ -15,6 +15,8 @@ # See the License for the specific language governing permissions and # limitations under the License. # +# SPDX-License-Identifier: Apache-2.0 +# ############################################################################## # @@ -55,7 +57,7 @@ # Darwin, MinGW, and NonStop. # # (3) This script is generated from the Groovy template -# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt # within the Gradle project. # # You can find Gradle at https://github.com/gradle/gradle/. @@ -83,10 +85,8 @@ done # This is normally unused # shellcheck disable=SC2034 APP_BASE_NAME=${0##*/} -APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit - -# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' +# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) +APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s\n' "$PWD" ) || exit # Use the maximum available, or set MAX_FD != -1 to use that value. MAX_FD=maximum @@ -133,10 +133,13 @@ location of your Java installation." fi else JAVACMD=java - which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + if ! command -v java >/dev/null 2>&1 + then + die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. Please set the JAVA_HOME variable in your environment to match the location of your Java installation." + fi fi # Increase the maximum file descriptors if we can. @@ -144,7 +147,7 @@ if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then case $MAX_FD in #( max*) # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. - # shellcheck disable=SC3045 + # shellcheck disable=SC2039,SC3045 MAX_FD=$( ulimit -H -n ) || warn "Could not query maximum file descriptor limit" esac @@ -152,7 +155,7 @@ if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then '' | soft) :;; #( *) # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. - # shellcheck disable=SC3045 + # shellcheck disable=SC2039,SC3045 ulimit -n "$MAX_FD" || warn "Could not set maximum file descriptor limit to $MAX_FD" esac @@ -197,11 +200,15 @@ if "$cygwin" || "$msys" ; then done fi -# Collect all arguments for the java command; -# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of -# shell script including quotes and variable substitutions, so put them in -# double quotes to make sure that they get re-expanded; and -# * put everything else in single quotes, so that it's not re-expanded. + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Collect all arguments for the java command: +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, +# and any embedded shellness will be escaped. +# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be +# treated as '${Hostname}' itself on the command line. set -- \ "-Dorg.gradle.appname=$APP_BASE_NAME" \ diff --git a/gradlew.bat b/gradlew.bat index 6689b85..9b42019 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -13,6 +13,8 @@ @rem See the License for the specific language governing permissions and @rem limitations under the License. @rem +@rem SPDX-License-Identifier: Apache-2.0 +@rem @if "%DEBUG%"=="" @echo off @rem ########################################################################## @@ -43,11 +45,11 @@ set JAVA_EXE=java.exe %JAVA_EXE% -version >NUL 2>&1 if %ERRORLEVEL% equ 0 goto execute -echo. -echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. +echo. 1>&2 +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 goto fail @@ -57,11 +59,11 @@ set JAVA_EXE=%JAVA_HOME%/bin/java.exe if exist "%JAVA_EXE%" goto execute -echo. -echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. +echo. 1>&2 +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 goto fail diff --git a/src/integTest/java/org/sonatype/gradle/plugins/scan/ScanIT_Gradle_Versions_8_11_to_8_13.java b/src/integTest/java/org/sonatype/gradle/plugins/scan/ScanIT_Gradle_Versions_8_11_to_8_14.java similarity index 84% rename from src/integTest/java/org/sonatype/gradle/plugins/scan/ScanIT_Gradle_Versions_8_11_to_8_13.java rename to src/integTest/java/org/sonatype/gradle/plugins/scan/ScanIT_Gradle_Versions_8_11_to_8_14.java index d1d6452..573f0fb 100644 --- a/src/integTest/java/org/sonatype/gradle/plugins/scan/ScanIT_Gradle_Versions_8_11_to_8_13.java +++ b/src/integTest/java/org/sonatype/gradle/plugins/scan/ScanIT_Gradle_Versions_8_11_to_8_14.java @@ -19,15 +19,15 @@ import org.junit.runners.Parameterized; -public class ScanIT_Gradle_Versions_8_11_to_8_13 +public class ScanIT_Gradle_Versions_8_11_to_8_14 extends ScanPluginIntegrationTestBase { @Parameterized.Parameters(name = "Version: {0}") public static List data() { - return List.of("8.11.1", "8.12.1", "8.13"); + return List.of("8.11.1", "8.12.1", "8.14"); } - public ScanIT_Gradle_Versions_8_11_to_8_13(final String gradleVersion) { + public ScanIT_Gradle_Versions_8_11_to_8_14(final String gradleVersion) { super(gradleVersion); } } diff --git a/src/main/java/org/sonatype/gradle/plugins/scan/ScanPlugin.java b/src/main/java/org/sonatype/gradle/plugins/scan/ScanPlugin.java index 4666b20..eaf29f6 100644 --- a/src/main/java/org/sonatype/gradle/plugins/scan/ScanPlugin.java +++ b/src/main/java/org/sonatype/gradle/plugins/scan/ScanPlugin.java @@ -15,9 +15,6 @@ */ package org.sonatype.gradle.plugins.scan; -import org.gradle.api.Action; -import org.gradle.api.Task; -import org.gradle.util.GradleVersion; import org.sonatype.gradle.plugins.scan.nexus.iq.index.NexusIqIndexTask; import org.sonatype.gradle.plugins.scan.nexus.iq.index.NexusIqPluginIndexExtension; import org.sonatype.gradle.plugins.scan.nexus.iq.scan.NexusIqPluginScanExtension; @@ -25,14 +22,14 @@ import org.sonatype.gradle.plugins.scan.ossindex.OssIndexAuditTask; import org.sonatype.gradle.plugins.scan.ossindex.OssIndexPluginExtension; +import org.gradle.api.Action; import org.gradle.api.Plugin; import org.gradle.api.Project; +import org.gradle.api.Task; +import org.gradle.util.GradleVersion; public class ScanPlugin implements Plugin { - private static final boolean IS_GRADLE_MIN_4_9 = - GradleVersion.current().compareTo(GradleVersion.version("4.9-rc-1")) >= 0; - private static final boolean IS_GRADLE_MIN_7_4 = GradleVersion.current().compareTo(GradleVersion.version("7.4")) >= 0; @@ -73,11 +70,12 @@ public void apply(Project project) { }); } - private static void createTask(Project project, String name, Class type, Action configuration) { - if (IS_GRADLE_MIN_4_9) { - project.getTasks().register(name, type, configuration); - } else { - project.getTasks().create(name, type, configuration); - } + private static void createTask( + Project project, + String name, + Class type, + Action configuration) + { + project.getTasks().register(name, type, configuration); } } diff --git a/src/main/java/org/sonatype/gradle/plugins/scan/common/DependenciesFinder.java b/src/main/java/org/sonatype/gradle/plugins/scan/common/DependenciesFinder.java index f449e41..03297fc 100644 --- a/src/main/java/org/sonatype/gradle/plugins/scan/common/DependenciesFinder.java +++ b/src/main/java/org/sonatype/gradle/plugins/scan/common/DependenciesFinder.java @@ -39,22 +39,11 @@ import org.gradle.api.artifacts.Configuration; import org.gradle.api.artifacts.DependencySet; import org.gradle.api.artifacts.ModuleVersionIdentifier; -import org.gradle.api.artifacts.ProjectDependency; -import org.gradle.api.artifacts.ResolveException; import org.gradle.api.artifacts.ResolvedArtifact; -import org.gradle.api.artifacts.ResolvedConfiguration; import org.gradle.api.artifacts.ResolvedDependency; import org.gradle.api.attributes.Attribute; -import org.gradle.api.attributes.AttributeContainer; -import org.gradle.api.attributes.AttributeMatchingStrategy; -import org.gradle.api.attributes.Usage; -import org.gradle.api.internal.artifacts.result.DefaultResolvedDependencyResult; -import org.gradle.api.model.ObjectFactory; import org.gradle.api.plugins.PluginContainer; import org.gradle.internal.impldep.com.google.common.annotations.VisibleForTesting; -import org.gradle.util.GradleVersion; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import static org.gradle.api.plugins.JavaPlugin.COMPILE_CLASSPATH_CONFIGURATION_NAME; import static org.gradle.api.plugins.JavaPlugin.COMPILE_ONLY_CONFIGURATION_NAME; @@ -62,10 +51,6 @@ public class DependenciesFinder { - private final Logger log = LoggerFactory.getLogger(DependenciesFinder.class); - - static final String BUILD_TYPE_ATTR_NAME = "com.android.build.api.attributes.BuildTypeAttr"; - private static final String RELEASE_COMPILE_LEGACY_CONFIGURATION_NAME = "_releaseCompile"; private static final String RELEASE_RUNTIME_APK_LEGACY_CONFIGURATION_NAME = "_releaseApk"; @@ -85,26 +70,21 @@ public class DependenciesFinder RELEASE_COMPILE_CONFIGURATION_NAME, RELEASE_RUNTIME_CONFIGURATION_NAME); - private static final String COPY_CONFIGURATION_NAME = "sonatypeCopyConfiguration"; - - private static final String ATTRIBUTES_SUPPORTED_GRADLE_VERSION = "4.0"; - - private static final Function> CONFIGURATION_DEPENDENCIES_FUNCTION = - resolvedConfiguration -> resolvedConfiguration.getFirstLevelModuleDependencies().stream(); - public Set findResolvedDependencies( Project project, boolean allConfigurations, Map variantAttributes, boolean excludeCompileOnlyDependencies) { + addDisambiguationRules(project, variantAttributes); + Set compileOnlyDependenciesIds = excludeCompileOnlyDependencies ? getCompileOnlyDependencyIds(project) : Collections.emptySet(); return new LinkedHashSet<>(new LinkedHashSet<>(project.getConfigurations()).stream() .filter(configuration -> isAcceptableConfiguration(configuration, allConfigurations)).flatMap(configuration -> { Stream dependencies = - getDependencies(project, configuration, variantAttributes, CONFIGURATION_DEPENDENCIES_FUNCTION); + configuration.getResolvedConfiguration().getFirstLevelModuleDependencies().stream(); if (!compileOnlyDependenciesIds.isEmpty() && shouldRemoveCompileOnlyDependencies(project, configuration)) { Set filteredDependencies = @@ -129,13 +109,16 @@ public List findModules( List modules = new ArrayList<>(); rootProject.allprojects(project -> { + + addDisambiguationRules(project, variantAttributes); + if (!modulesExcluded.contains(project.getName())) { Module module = buildModule(project); Set compileOnlyDependenciesIds = excludeCompileOnlyDependencies ? getCompileOnlyDependencyIds(project) : Collections.emptySet(); - findResolvedArtifacts(project, allConfigurations, variantAttributes, compileOnlyDependenciesIds).stream() + findResolvedArtifacts(project, allConfigurations, compileOnlyDependenciesIds).stream() .map(resolvedArtifact -> new Artifact() .setId(getArtifactId(resolvedArtifact)) .setPathname(resolvedArtifact.getFile()) @@ -152,24 +135,40 @@ public List findModules( return modules; } + private void addDisambiguationRules(Project project, Map variantAttributes) { + project.getDependencies().attributesSchema(attributesSchema -> { + if (isAndroidProject(project)) { + attributesSchema + .attribute(Attribute.of("artifactType", String.class)) + .getDisambiguationRules() + .add(AndroidArtifactTypeAttributeDisambiguationRule.class); + } + + if (variantAttributes != null) { + variantAttributes.forEach((attributeName, attributeValue) -> attributesSchema + .attribute(Attribute.of(attributeName, String.class), strategy -> strategy + .getDisambiguationRules() + .add(VariantAttributeDisambiguationRule.class, config -> config.params(attributeValue)))); + } + }); + } + @VisibleForTesting Set findResolvedArtifacts( Project project, boolean allConfigurations, - Map variantAttributes, Set compileOnlyDependenciesIds) { return new LinkedHashSet<>(project.getConfigurations()).stream() .filter(configuration -> isAcceptableConfiguration(configuration, allConfigurations)).flatMap(configuration -> { - Stream artifacts = getDependencies(project, configuration, variantAttributes, - resolvedConfiguration -> resolvedConfiguration.getResolvedArtifacts().stream()); + Stream artifacts = configuration.getResolvedConfiguration().getResolvedArtifacts().stream(); if (!compileOnlyDependenciesIds.isEmpty() && shouldRemoveCompileOnlyDependencies(project, configuration)) { Set filteredArtifacts = artifacts.collect(Collectors.toSet()); Set dependenciesToRemove = new HashSet<>(); - getDependencies(project, configuration, variantAttributes, CONFIGURATION_DEPENDENCIES_FUNCTION) + configuration.getResolvedConfiguration().getFirstLevelModuleDependencies().stream() .filter(dependency -> compileOnlyDependenciesIds.contains(getResolvedDependencyId(dependency))) .forEach(dependency -> fillAllChildDependencies(dependency, dependenciesToRemove)); @@ -224,137 +223,12 @@ private String getResolvedDependencyId(ResolvedDependency resolvedDependency) { + resolvedDependency.getModuleVersion(); } - @VisibleForTesting - Configuration createCopyConfiguration(Project project, Map variantAttributes) { - String configurationName = COPY_CONFIGURATION_NAME; - for (int i = 0; project.getConfigurations().findByName(configurationName) != null; i++) { - configurationName += i; - } - Configuration copyConfiguration = project.getConfigurations().create(configurationName); - - if (isGradleVersionSupportedForAttributes(project.getGradle().getGradleVersion())) { - boolean isAndroidProject = isAndroidProject(project); - - if (isAndroidProject) { - AttributeMatchingStrategy artifactTypeMatchingStrategy = - project.getDependencies().getAttributesSchema().attribute(Attribute.of("artifactType", String.class)); - artifactTypeMatchingStrategy.getDisambiguationRules().add(AndroidArtifactTypeAttributeDisambiguationRule.class); - } - - copyConfiguration.attributes(attributeContainer -> { - ObjectFactory factory = project.getObjects(); - attributeContainer.attribute(Usage.USAGE_ATTRIBUTE, factory.named(Usage.class, Usage.JAVA_RUNTIME)); - - variantAttributes.forEach((attributeName, value) -> { - attributeContainer.attribute(Attribute.of(attributeName, String.class), value); - }); - - if (isAndroidProject) { - addReleaseBuildTypeAttribute(project, attributeContainer); - } - }); - } - return copyConfiguration; - } - - @SuppressWarnings({"unchecked", "rawtypes"}) - private void addReleaseBuildTypeAttribute(Project project, AttributeContainer attributeContainer) { - if (GradleVersion.current().compareTo(GradleVersion.version("6.0.1")) >= 0) { - attributeContainer.attribute(Attribute.of(BUILD_TYPE_ATTR_NAME, String.class), "release"); - } - else { - Set configurationNames = new HashSet(CONFIGURATION_NAMES); - configurationNames.add("fullReleaseRuntimeElements"); - - for (String configurationName : configurationNames) { - Configuration configuration = project.getConfigurations().findByName(configurationName); - Attribute attributeFound = null; - Object attributeValue = null; - - if (configuration != null) { - for (Attribute attribute : configuration.getAttributes().keySet()) { - if (BUILD_TYPE_ATTR_NAME.equals(attribute.getName())) { - attributeFound = attribute; - attributeValue = configuration.getAttributes().getAttribute(attributeFound); - break; - } - } - } - - if (attributeFound != null) { - attributeContainer.attribute(Attribute.of(BUILD_TYPE_ATTR_NAME, attributeFound.getType()), attributeValue); - break; - } - } - } - } - - @VisibleForTesting - boolean isGradleVersionSupportedForAttributes(String gradleVersion) { - return gradleVersion.compareTo(ATTRIBUTES_SUPPORTED_GRADLE_VERSION) >= 0; - } - @VisibleForTesting boolean isAndroidProject(Project project) { PluginContainer pluginContainer = project.getPlugins(); return pluginContainer.hasPlugin("com.android.application") || pluginContainer.hasPlugin("com.android.library"); } - @VisibleForTesting - Stream getDependencies( - Project project, - Configuration originalConfiguration, - Map variantAttributes, - Function> function) - { - try { - return function.apply(originalConfiguration.getResolvedConfiguration()); - } - catch (ResolveException e) { - Configuration copyConfiguration = copyDependencies(project, originalConfiguration, false, variantAttributes); - - try { - return function.apply(copyConfiguration.getResolvedConfiguration()); - } - catch (ResolveException lastResortException) { - copyConfiguration = copyDependencies(project, originalConfiguration, true, variantAttributes); - return function.apply(copyConfiguration.getResolvedConfiguration()); - } - } - } - - private Configuration copyDependencies( - Project project, - Configuration originalConfiguration, - boolean skipUnresolvableDependencies, - Map variantAttributes) - { - Configuration copyConfiguration = createCopyConfiguration(project, variantAttributes); - - Set resolvedDependencies = !skipUnresolvableDependencies - ? Collections.emptySet() - : originalConfiguration.getIncoming().getResolutionResult().getAllDependencies() - .stream() - .filter(dependency -> dependency instanceof DefaultResolvedDependencyResult) - .map(dependency -> ((DefaultResolvedDependencyResult) dependency).getSelected().getId().getDisplayName()) - .collect(Collectors.toSet()); - - originalConfiguration.getAllDependencies().all(dependency -> { - copyConfiguration.getDependencies().add(dependency); - - if (skipUnresolvableDependencies - && !(dependency instanceof ProjectDependency) - && !resolvedDependencies.contains(getDependencyId(dependency))) { - log.warn("Unable to process the dependency {}:{}:{} in project {} and configuration {}", dependency.getGroup(), - dependency.getName(), dependency.getVersion(), project.getName(), originalConfiguration.getName()); - - copyConfiguration.getDependencies().remove(dependency); - } - }); - - return copyConfiguration; - } - @VisibleForTesting Dependency processDependency( ResolvedDependency resolvedDependency, @@ -402,8 +276,6 @@ private boolean isParent( } private boolean isAcceptableConfiguration(Configuration configuration, boolean allConfigurations) { - if (configuration.getName().endsWith(COPY_CONFIGURATION_NAME)) - return false; if (allConfigurations) { return configuration.isCanBeResolved(); } diff --git a/src/main/java/org/sonatype/gradle/plugins/scan/common/VariantAttributeDisambiguationRule.java b/src/main/java/org/sonatype/gradle/plugins/scan/common/VariantAttributeDisambiguationRule.java new file mode 100644 index 0000000..af29c62 --- /dev/null +++ b/src/main/java/org/sonatype/gradle/plugins/scan/common/VariantAttributeDisambiguationRule.java @@ -0,0 +1,24 @@ +package org.sonatype.gradle.plugins.scan.common; + +import javax.inject.Inject; + +import org.gradle.api.attributes.AttributeDisambiguationRule; +import org.gradle.api.attributes.MultipleCandidatesDetails; + +public class VariantAttributeDisambiguationRule + implements AttributeDisambiguationRule +{ + private final String variantValue; + + @Inject + public VariantAttributeDisambiguationRule(String variantValue) { + this.variantValue = variantValue; + } + + @Override + public void execute(MultipleCandidatesDetails details) { + if (details.getCandidateValues().contains(variantValue)) { + details.closestMatch(variantValue); + } + } +} diff --git a/src/test/java/org/sonatype/gradle/plugins/scan/common/DependenciesFinderTest.java b/src/test/java/org/sonatype/gradle/plugins/scan/common/DependenciesFinderTest.java index e134857..606a502 100644 --- a/src/test/java/org/sonatype/gradle/plugins/scan/common/DependenciesFinderTest.java +++ b/src/test/java/org/sonatype/gradle/plugins/scan/common/DependenciesFinderTest.java @@ -16,34 +16,24 @@ package org.sonatype.gradle.plugins.scan.common; import java.util.Collections; +import java.util.Comparator; import java.util.HashSet; import java.util.List; -import java.util.Map; import java.util.Set; -import java.util.stream.Collectors; import java.util.stream.Stream; import com.sonatype.insight.scan.module.model.Artifact; import com.sonatype.insight.scan.module.model.Dependency; import com.sonatype.insight.scan.module.model.Module; -import com.google.common.collect.ImmutableMap; import com.google.common.collect.Sets; import org.gradle.api.Project; import org.gradle.api.artifacts.Configuration; import org.gradle.api.artifacts.ConfigurationContainer; -import org.gradle.api.artifacts.ModuleVersionIdentifier; import org.gradle.api.artifacts.ResolveException; import org.gradle.api.artifacts.ResolvedArtifact; import org.gradle.api.artifacts.ResolvedDependency; import org.gradle.api.artifacts.dsl.DependencyHandler; -import org.gradle.api.attributes.Attribute; -import org.gradle.api.attributes.AttributeContainer; -import org.gradle.api.attributes.Usage; -import org.gradle.api.internal.artifacts.DefaultModuleVersionIdentifier; -import org.gradle.api.internal.artifacts.DefaultResolvedDependency; -import org.gradle.api.internal.artifacts.ResolvedConfigurationIdentifier; -import org.gradle.api.plugins.PluginContainer; import org.gradle.testfixtures.ProjectBuilder; import org.junit.Before; import org.junit.Test; @@ -202,42 +192,42 @@ public void testFindResolvedDependencies_excludeCompileOnlyDependencies() { @Test public void testFindResolvedArtifacts_includeCompileDependencies() { Project project = buildProject(IMPLEMENTATION_CONFIGURATION_NAME, false); - Set result = finder.findResolvedArtifacts(project, false, emptyMap(), emptySet()); + Set result = finder.findResolvedArtifacts(project, false, emptySet()); assertThat(result).hasSize(1); } @Test public void testFindResolvedArtifacts_includeRuntimeDependencies() { Project project = buildProject(RUNTIME_ONLY_CONFIGURATION_NAME, false); - Set result = finder.findResolvedArtifacts(project, false, emptyMap(), emptySet()); + Set result = finder.findResolvedArtifacts(project, false, emptySet()); assertThat(result).hasSize(1); } @Test public void testFindResolvedArtifacts_includeAndroidCompileDependencies() { Project project = buildProject("releaseCompileClasspath", true); - Set result = finder.findResolvedArtifacts(project, false, emptyMap(), emptySet()); + Set result = finder.findResolvedArtifacts(project, false, emptySet()); assertThat(result).hasSize(1); } @Test public void testFindResolvedArtifacts_includeAndroidRuntimeDependencies() { Project project = buildProject("releaseRuntimeClasspath", true); - Set result = finder.findResolvedArtifacts(project, false, emptyMap(), emptySet()); + Set result = finder.findResolvedArtifacts(project, false, emptySet()); assertThat(result).hasSize(1); } @Test public void testFindResolvedArtifacts_omitTestDependencies() { Project project = buildProject(TEST_IMPLEMENTATION_CONFIGURATION_NAME, false); - Set result = finder.findResolvedArtifacts(project, false, emptyMap(), emptySet()); + Set result = finder.findResolvedArtifacts(project, false, emptySet()); assertThat(result).isEmpty(); } @Test public void testFindResolvedArtifacts_includeTestDependencies() { Project project = buildProject(TEST_IMPLEMENTATION_CONFIGURATION_NAME, false); - Set result = finder.findResolvedArtifacts(project, true, emptyMap(), emptySet()); + Set result = finder.findResolvedArtifacts(project, true, emptySet()); assertThat(result).hasSize(1); } @@ -245,7 +235,7 @@ public void testFindResolvedArtifacts_includeTestDependencies() { public void testFindResolvedArtifacts_omitCompileOnlyDependencies() { Project project = buildProject(COMPILE_ONLY_CONFIGURATION_NAME, false); Set result = - finder.findResolvedArtifacts(project, false, emptyMap(), Sets.newHashSet(COMMONS_COLLECTIONS_DEPENDENCY)); + finder.findResolvedArtifacts(project, false, Sets.newHashSet(COMMONS_COLLECTIONS_DEPENDENCY)); assertThat(result).isEmpty(); } @@ -352,169 +342,6 @@ public void testFindModules_excludeCompileOnlyDependencies() { assertThat(modules.get(0).getId()).isEqualTo(parentProject.getName()); } - @Test - public void testCreateCopyConfiguration() { - Project project = buildProject(IMPLEMENTATION_CONFIGURATION_NAME, false); - Configuration configuration = finder.createCopyConfiguration(project, emptyMap()); - - assertThat(configuration).isNotNull(); - assertThat(configuration.getName()).isEqualTo("sonatypeCopyConfiguration"); - - Usage expectedUsage = project.getObjects().named(Usage.class, Usage.JAVA_RUNTIME); - assertThat(configuration.getAttributes().getAttribute(Usage.USAGE_ATTRIBUTE)).isEqualTo(expectedUsage); - assertThat(configuration.getAttributes() - .getAttribute(Attribute.of(DependenciesFinder.BUILD_TYPE_ATTR_NAME, String.class))).isNull(); - } - - @Test - public void testCreateCopyConfiguration_WithVariantAttributes() { - Project project = buildProject(IMPLEMENTATION_CONFIGURATION_NAME, false); - Map variantAttributes = ImmutableMap.of("attribute1", "1", "attribute2", "2"); - - Configuration configuration = finder.createCopyConfiguration(project, variantAttributes); - - assertThat(configuration).isNotNull(); - AttributeContainer attributeContainer = configuration.getAttributes().getAttributes(); - - assertThat(attributeContainer.getAttribute(Attribute.of("attribute1", String.class))).isEqualTo("1"); - assertThat(attributeContainer.getAttribute(Attribute.of("attribute2", String.class))).isEqualTo("2"); - } - - @Test - public void testCreateCopyConfiguration_AndroidProject() { - PluginContainer pluginContainer = mock(PluginContainer.class); - when(pluginContainer.hasPlugin("com.android.application")).thenReturn(true); - - Project project = spy(buildProject(IMPLEMENTATION_CONFIGURATION_NAME, false)); - when(project.getPlugins()).thenReturn(pluginContainer); - - Configuration configuration = finder.createCopyConfiguration(project, emptyMap()); - - assertThat(configuration).isNotNull(); - assertThat(configuration.getName()).isEqualTo("sonatypeCopyConfiguration"); - - Usage expectedUsage = project.getObjects().named(Usage.class, Usage.JAVA_RUNTIME); - assertThat(configuration.getAttributes().getAttribute(Usage.USAGE_ATTRIBUTE)).isEqualTo(expectedUsage); - assertThat( - configuration.getAttributes().getAttribute(Attribute.of(DependenciesFinder.BUILD_TYPE_ATTR_NAME, String.class))) - .isEqualTo("release"); - } - - @Test - public void testIsGradleVersionSupportedForAttributes() { - assertThat(finder.isGradleVersionSupportedForAttributes("3.5")).isFalse(); - assertThat(finder.isGradleVersionSupportedForAttributes("3.5.1")).isFalse(); - assertThat(finder.isGradleVersionSupportedForAttributes("4.0")).isTrue(); - assertThat(finder.isGradleVersionSupportedForAttributes("4.0.1")).isTrue(); - assertThat(finder.isGradleVersionSupportedForAttributes("4.0.2")).isTrue(); - assertThat(finder.isGradleVersionSupportedForAttributes("4.1")).isTrue(); - } - - @Test - public void testGetDependencies_ModuleDependencies() { - Project project = buildProject(IMPLEMENTATION_CONFIGURATION_NAME, false); - Configuration originalConfiguration = project.getConfigurations().getByName(IMPLEMENTATION_CONFIGURATION_NAME); - originalConfiguration.setCanBeResolved(true); - - Stream dependencies = finder.getDependencies(project, originalConfiguration, emptyMap(), - resolvedConfiguration -> resolvedConfiguration.getFirstLevelModuleDependencies().stream()); - - assertThat(dependencies).isNotNull(); - - List list = dependencies.collect(Collectors.toList()); - assertThat(list).hasSize(1); - - Set artifacts = list.get(0).getAllModuleArtifacts(); - assertThat(artifacts).hasSize(1); - assertThat(artifacts.iterator().next().getId().getComponentIdentifier().toString()) - .isEqualTo(COMMONS_COLLECTIONS_DEPENDENCY); - } - - @Test - public void testGetDependencies_ModuleDependencies_WithError() { - Project project = buildProject(IMPLEMENTATION_CONFIGURATION_NAME, false); - - Configuration originalConfiguration = mock(Configuration.class); - when(originalConfiguration.getResolvedConfiguration()).thenThrow(ResolveException.class); - when(originalConfiguration.getAllDependencies()) - .thenReturn(project.getConfigurations().getByName(IMPLEMENTATION_CONFIGURATION_NAME).getAllDependencies()); - - Stream dependencies = finder.getDependencies(project, originalConfiguration, emptyMap(), - resolvedConfiguration -> resolvedConfiguration.getFirstLevelModuleDependencies().stream()); - - assertThat(dependencies).isNotNull(); - - List list = dependencies.collect(Collectors.toList()); - assertThat(list).hasSize(1); - - Set artifacts = list.get(0).getAllModuleArtifacts(); - assertThat(artifacts).hasSize(1); - assertThat(artifacts.iterator().next().getId().getComponentIdentifier().toString()) - .isEqualTo(COMMONS_COLLECTIONS_DEPENDENCY); - } - - @Test - public void testGetDependencies_ResolvedArtifacts() { - Project project = buildProject(IMPLEMENTATION_CONFIGURATION_NAME, false); - Configuration originalConfiguration = project.getConfigurations().getByName(IMPLEMENTATION_CONFIGURATION_NAME); - originalConfiguration.setCanBeResolved(true); - - Stream dependencies = finder.getDependencies(project, originalConfiguration, emptyMap(), - resolvedConfiguration -> resolvedConfiguration.getResolvedArtifacts().stream()); - - assertThat(dependencies).isNotNull(); - - List list = dependencies.collect(Collectors.toList()); - - assertThat(list).hasSize(1); - assertThat(list.get(0).getId().getComponentIdentifier().toString()).isEqualTo(COMMONS_COLLECTIONS_DEPENDENCY); - } - - @Test - public void testGetDependencies_ResolvedArtifacts_WithError() { - Project project = buildProject(IMPLEMENTATION_CONFIGURATION_NAME, false); - - Configuration originalConfiguration = mock(Configuration.class); - when(originalConfiguration.getResolvedConfiguration()).thenThrow(ResolveException.class); - when(originalConfiguration.getAllDependencies()) - .thenReturn(project.getConfigurations().getByName(IMPLEMENTATION_CONFIGURATION_NAME).getAllDependencies()); - - Stream dependencies = finder.getDependencies(project, originalConfiguration, emptyMap(), - resolvedConfiguration -> resolvedConfiguration.getResolvedArtifacts().stream()); - - assertThat(dependencies).isNotNull(); - - List list = dependencies.collect(Collectors.toList()); - - assertThat(list).hasSize(1); - assertThat(list.get(0).getId().getComponentIdentifier().toString()).isEqualTo(COMMONS_COLLECTIONS_DEPENDENCY); - } - - @Test - public void testGetDependencies_ResolvedArtifacts_Skip_Unresolvable_Dependencies() { - Project project = buildProject(IMPLEMENTATION_CONFIGURATION_NAME, false); - DependencyHandler dependencyHandler = project.getDependencies(); - dependencyHandler.add(IMPLEMENTATION_CONFIGURATION_NAME, "test_group-test_artifact:0.0.1"); - - Configuration realConfiguration = project.getConfigurations().getByName(IMPLEMENTATION_CONFIGURATION_NAME); - realConfiguration.setCanBeResolved(true); - - Configuration mockConfiguration = mock(Configuration.class); - when(mockConfiguration.getResolvedConfiguration()).thenThrow(ResolveException.class); - when(mockConfiguration.getIncoming()).thenReturn(realConfiguration.getIncoming()); - when(mockConfiguration.getAllDependencies()).thenReturn(realConfiguration.getAllDependencies()); - - Stream dependencies = finder.getDependencies(project, mockConfiguration, emptyMap(), - resolvedConfiguration -> resolvedConfiguration.getResolvedArtifacts().stream()); - - assertThat(dependencies).isNotNull(); - - List list = dependencies.collect(Collectors.toList()); - - assertThat(list).hasSize(1); - assertThat(list.get(0).getId().getComponentIdentifier().toString()).isEqualTo(COMMONS_COLLECTIONS_DEPENDENCY); - } - @Test public void testProcessDependency() { testProcessDependency(false); @@ -526,39 +353,29 @@ public void testProcessDependency_avoidCircularDependenciesStackOverflowError() } private void testProcessDependency(boolean setupCircularDependencies) { - ModuleVersionIdentifier parentModuleVersionIdentifier = DefaultModuleVersionIdentifier.newId("g", "a", "v"); - ResolvedConfigurationIdentifier parentResolvedConfigurationIdentifier = new ResolvedConfigurationIdentifier( - parentModuleVersionIdentifier, ""); - DefaultResolvedDependency parentDependency = new DefaultResolvedDependency( - parentResolvedConfigurationIdentifier, null); - - ModuleVersionIdentifier singleChildModuleVersionIdentifier = DefaultModuleVersionIdentifier.newId( - "g2", "a2", "v2"); - ResolvedConfigurationIdentifier singleChildResolvedConfigurationIdentifier = new ResolvedConfigurationIdentifier( - singleChildModuleVersionIdentifier, ""); - DefaultResolvedDependency singleChildDependency = new DefaultResolvedDependency( - singleChildResolvedConfigurationIdentifier, null); - - ModuleVersionIdentifier multiChildModuleVersionIdentifier = DefaultModuleVersionIdentifier.newId("g3", "a3", "v3"); - ResolvedConfigurationIdentifier multiChildResolvedConfigurationIdentifier = new ResolvedConfigurationIdentifier( - multiChildModuleVersionIdentifier, ""); - DefaultResolvedDependency multiChildDependency = new DefaultResolvedDependency( - multiChildResolvedConfigurationIdentifier, null); - - ModuleVersionIdentifier subChildModuleVersionIdentifier = DefaultModuleVersionIdentifier.newId("g4", "a4", "v4"); - ResolvedConfigurationIdentifier subChildResolvedConfigurationIdentifier = new ResolvedConfigurationIdentifier( - subChildModuleVersionIdentifier, ""); - DefaultResolvedDependency subChildDependency = new DefaultResolvedDependency( - subChildResolvedConfigurationIdentifier, null); - - multiChildDependency.addChild(subChildDependency); + ResolvedDependency parentDependency = mock(ResolvedDependency.class); + when(parentDependency.getName()).thenReturn("g:a:v"); + + ResolvedDependency singleChildDependency = mock(ResolvedDependency.class); + when(singleChildDependency.getName()).thenReturn("g2:a2:v2"); + + ResolvedDependency multiChildDependency = mock(ResolvedDependency.class); + when(multiChildDependency.getName()).thenReturn("g3:a3:v3"); + + ResolvedDependency subChildDependency = mock(ResolvedDependency.class); + when(subChildDependency.getName()).thenReturn("g4:a4:v4"); + + when(multiChildDependency.getChildren()).thenReturn(Set.of(subChildDependency)); + when(subChildDependency.getParents()).thenReturn(Set.of(multiChildDependency)); if (setupCircularDependencies) { - singleChildDependency.addChild(parentDependency); + when(singleChildDependency.getChildren()).thenReturn(Set.of(parentDependency)); + when(parentDependency.getParents()).thenReturn(Set.of(singleChildDependency)); } - parentDependency.addChild(singleChildDependency); - parentDependency.addChild(multiChildDependency); + when(parentDependency.getChildren()).thenReturn(Set.of(singleChildDependency, multiChildDependency)); + when(singleChildDependency.getParents()).thenReturn(Set.of(parentDependency)); + when(multiChildDependency.getParents()).thenReturn(Set.of(parentDependency)); Dependency dependency = finder.processDependency(parentDependency, true, new HashSet<>()); assertThat(dependency).isNotNull(); @@ -566,6 +383,8 @@ private void testProcessDependency(boolean setupCircularDependencies) { assertThat(dependency.getId()).isEqualTo("g:a:v"); assertThat(dependency.getDependencies()).hasSize(2); + Collections.sort(dependency.getDependencies(), Comparator.comparing(Dependency::getId)); + Dependency child1 = dependency.getDependencies().get(0); assertThat(child1.isDirect()).isFalse(); assertThat(child1.getId()).isEqualTo("g2:a2:v2"); diff --git a/src/test/java/org/sonatype/gradle/plugins/scan/ossindex/OssIndexAuditTaskTest.java b/src/test/java/org/sonatype/gradle/plugins/scan/ossindex/OssIndexAuditTaskTest.java index cd0169b..41ed720 100644 --- a/src/test/java/org/sonatype/gradle/plugins/scan/ossindex/OssIndexAuditTaskTest.java +++ b/src/test/java/org/sonatype/gradle/plugins/scan/ossindex/OssIndexAuditTaskTest.java @@ -18,6 +18,7 @@ import java.net.URI; import java.util.Collections; import java.util.Map; +import java.util.Set; import java.util.function.BiConsumer; import org.sonatype.goodies.packageurl.PackageUrl; @@ -31,12 +32,10 @@ import com.google.common.collect.ImmutableMap; import org.gradle.api.GradleException; import org.gradle.api.Project; -import org.gradle.api.artifacts.ModuleVersionIdentifier; import org.gradle.api.artifacts.ResolvedDependency; +import org.gradle.api.artifacts.ResolvedModuleVersion; import org.gradle.api.artifacts.dsl.DependencyHandler; import org.gradle.api.internal.artifacts.DefaultModuleVersionIdentifier; -import org.gradle.api.internal.artifacts.DefaultResolvedDependency; -import org.gradle.api.internal.artifacts.ResolvedConfigurationIdentifier; import org.gradle.testfixtures.ProjectBuilder; import org.junit.Test; import org.junit.runner.RunWith; @@ -50,6 +49,7 @@ import static org.mockito.ArgumentMatchers.anyList; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.verify; @@ -158,36 +158,36 @@ public void testAudit_simulated() throws Exception { @Test public void testBuildDependenciesMap_avoidCircularDependenciesStackOverflowError() { - ModuleVersionIdentifier parentModuleVersionIdentifier = DefaultModuleVersionIdentifier.newId("g", "a", "v"); - ResolvedConfigurationIdentifier parentResolvedConfigurationIdentifier = - new ResolvedConfigurationIdentifier(parentModuleVersionIdentifier, ""); - DefaultResolvedDependency parentDependency = - new DefaultResolvedDependency(parentResolvedConfigurationIdentifier, null); - - ModuleVersionIdentifier singleChildModuleVersionIdentifier = DefaultModuleVersionIdentifier.newId("g2", "a2", "v2"); - ResolvedConfigurationIdentifier singleChildResolvedConfigurationIdentifier = - new ResolvedConfigurationIdentifier(singleChildModuleVersionIdentifier, ""); - DefaultResolvedDependency singleChildDependency = - new DefaultResolvedDependency(singleChildResolvedConfigurationIdentifier, null); - - ModuleVersionIdentifier multiChildModuleVersionIdentifier = DefaultModuleVersionIdentifier.newId("g3", "a3", "v3"); - ResolvedConfigurationIdentifier multiChildResolvedConfigurationIdentifier = - new ResolvedConfigurationIdentifier(multiChildModuleVersionIdentifier, ""); - DefaultResolvedDependency multiChildDependency = - new DefaultResolvedDependency(multiChildResolvedConfigurationIdentifier, null); - - ModuleVersionIdentifier subChildModuleVersionIdentifier = DefaultModuleVersionIdentifier.newId("g4", "a4", "v4"); - ResolvedConfigurationIdentifier subChildResolvedConfigurationIdentifier = - new ResolvedConfigurationIdentifier(subChildModuleVersionIdentifier, ""); - DefaultResolvedDependency subChildDependency = - new DefaultResolvedDependency(subChildResolvedConfigurationIdentifier, null); - - multiChildDependency.addChild(subChildDependency); + ResolvedDependency parentDependency = mock(ResolvedDependency.class); + + ResolvedModuleVersion resolvedModuleVersion = mock(ResolvedModuleVersion.class); + when(resolvedModuleVersion.getId()).thenReturn(DefaultModuleVersionIdentifier.newId("g", "a", "v")); + when(parentDependency.getModule()).thenReturn(resolvedModuleVersion); + + ResolvedDependency singleChildDependency = mock(ResolvedDependency.class); + + ResolvedModuleVersion resolvedModuleVersion2 = mock(ResolvedModuleVersion.class); + when(resolvedModuleVersion2.getId()).thenReturn(DefaultModuleVersionIdentifier.newId("g2", "a2", "v2")); + when(singleChildDependency.getModule()).thenReturn(resolvedModuleVersion2); + + ResolvedDependency multiChildDependency = mock(ResolvedDependency.class); + + ResolvedModuleVersion resolvedModuleVersion3 = mock(ResolvedModuleVersion.class); + when(resolvedModuleVersion3.getId()).thenReturn(DefaultModuleVersionIdentifier.newId("g3", "a3", "v3")); + when(multiChildDependency.getModule()).thenReturn(resolvedModuleVersion3); + + ResolvedDependency subChildDependency = mock(ResolvedDependency.class); + + ResolvedModuleVersion resolvedModuleVersion4 = mock(ResolvedModuleVersion.class); + when(resolvedModuleVersion4.getId()).thenReturn(DefaultModuleVersionIdentifier.newId("g4", "a4", "v4")); + when(subChildDependency.getModule()).thenReturn(resolvedModuleVersion4); + + when(multiChildDependency.getChildren()).thenReturn(Set.of(subChildDependency)); // circular dependency - singleChildDependency.addChild(parentDependency); - parentDependency.addChild(singleChildDependency); - parentDependency.addChild(multiChildDependency); + when(singleChildDependency.getChildren()).thenReturn(Set.of(parentDependency)); + + when(parentDependency.getChildren()).thenReturn(Set.of(singleChildDependency, multiChildDependency)); OssIndexAuditTask taskSpy = buildAuditTaskSpy(true, null); BiMap dependenciesMap = HashBiMap.create(); @@ -218,7 +218,10 @@ public void testBuildResponseHandler_cycloneDxResponseHandler() { assertThat(taskSpy.buildResponseHandler()).isInstanceOf(CycloneDxResponseHandler.class); } - private OssIndexAuditTask buildAuditTaskSpy(boolean isSimulated, BiConsumer extensionContributor) { + private OssIndexAuditTask buildAuditTaskSpy( + boolean isSimulated, + BiConsumer extensionContributor) + { Project project = ProjectBuilder.builder().build(); project.getPluginManager().apply("java"); project.getRepositories().mavenCentral(); @@ -233,7 +236,7 @@ private OssIndexAuditTask buildAuditTaskSpy(boolean isSimulated, BiConsumer