mirror of https://github.com/grpc/grpc-java.git
Make custom tasks compatible with configuration cache
Gradle is forcing a move away from using 'project' during task excution and because of some interactions there, this is easiest by making them real classes. That makes them start looking quite strange in the build file, so they are now moved to buildSrc/. We could have continued using Groovy, but it is weird in some ways that are more apparent when making classes and not just scripting. Instead, they were converted to Java. They are compatible with delayed configuration resolution as well.
This commit is contained in:
parent
dca89b25bf
commit
7eb24d6ff0
103
build.gradle
103
build.gradle
|
|
@ -7,8 +7,9 @@ plugins {
|
||||||
id 'com.google.cloud.tools.jib' apply false
|
id 'com.google.cloud.tools.jib' apply false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
import io.grpc.gradle.CheckForUpdatesTask
|
||||||
|
import io.grpc.gradle.RequireUpperBoundDepsMatchTask
|
||||||
import net.ltgt.gradle.errorprone.CheckSeverity
|
import net.ltgt.gradle.errorprone.CheckSeverity
|
||||||
import org.gradle.util.GUtil
|
|
||||||
|
|
||||||
subprojects {
|
subprojects {
|
||||||
apply plugin: "checkstyle"
|
apply plugin: "checkstyle"
|
||||||
|
|
@ -275,15 +276,11 @@ subprojects {
|
||||||
plugins.withId("java-library") {
|
plugins.withId("java-library") {
|
||||||
// Detect Maven Enforcer's dependencyConvergence failures. We only care
|
// Detect Maven Enforcer's dependencyConvergence failures. We only care
|
||||||
// for artifacts used as libraries by others with Maven.
|
// for artifacts used as libraries by others with Maven.
|
||||||
tasks.register('checkUpperBoundDeps') {
|
tasks.register('checkUpperBoundDeps', RequireUpperBoundDepsMatchTask) {
|
||||||
inputs.files(configurations.runtimeClasspath).withNormalizer(ClasspathNormalizer)
|
configuration = configurations.getByName('runtimeClasspath')
|
||||||
outputs.file("${buildDir}/tmp/${name}") // Fake output for UP-TO-DATE checking
|
|
||||||
doLast {
|
|
||||||
requireUpperBoundDepsMatch(configurations.runtimeClasspath, project)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
tasks.named('assemble').configure {
|
tasks.named('assemble').configure {
|
||||||
dependsOn checkUpperBoundDeps
|
dependsOn tasks.named('checkUpperBoundDeps')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -456,64 +453,6 @@ subprojects {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class DepAndParents {
|
|
||||||
DependencyResult dep
|
|
||||||
List<String> parents
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Make sure that Maven would select the same versions as Gradle selected.
|
|
||||||
* This is essentially the same as if we used Maven Enforcer's
|
|
||||||
* requireUpperBoundDeps for our artifacts.
|
|
||||||
*/
|
|
||||||
def requireUpperBoundDepsMatch(Configuration conf, Project project) {
|
|
||||||
// artifact name => version
|
|
||||||
Map<String,String> golden = conf.resolvedConfiguration.resolvedArtifacts.collectEntries {
|
|
||||||
ResolvedArtifact it ->
|
|
||||||
ModuleVersionIdentifier id = it.moduleVersion.id
|
|
||||||
[id.group + ":" + id.name, id.version]
|
|
||||||
}
|
|
||||||
// Breadth-first search like Maven for dependency resolution
|
|
||||||
Queue<DepAndParents> queue = new ArrayDeque<>()
|
|
||||||
conf.incoming.resolutionResult.root.dependencies.each {
|
|
||||||
queue.add(new DepAndParents(dep: it, parents: [project.displayName]))
|
|
||||||
}
|
|
||||||
Set<String> found = new HashSet<>()
|
|
||||||
while (!queue.isEmpty()) {
|
|
||||||
DepAndParents depAndParents = queue.remove()
|
|
||||||
ResolvedDependencyResult result = (ResolvedDependencyResult) depAndParents.dep
|
|
||||||
ModuleVersionIdentifier id = result.selected.moduleVersion
|
|
||||||
String artifact = id.group + ":" + id.name
|
|
||||||
if (found.contains(artifact))
|
|
||||||
continue
|
|
||||||
found.add(artifact)
|
|
||||||
String version
|
|
||||||
if (result.requested instanceof ProjectComponentSelector) {
|
|
||||||
ProjectComponentSelector selector = (ProjectComponentSelector) result.requested
|
|
||||||
version = project.findProject(selector.projectPath).version
|
|
||||||
} else {
|
|
||||||
version = ((ModuleComponentSelector) result.requested).version
|
|
||||||
}
|
|
||||||
String goldenVersion = golden[artifact]
|
|
||||||
if (goldenVersion != version && "[$goldenVersion]" != version) {
|
|
||||||
throw new RuntimeException(
|
|
||||||
"Maven version skew: $artifact ($version != $goldenVersion) "
|
|
||||||
+ "Bad version dependency path: " + depAndParents.parents
|
|
||||||
+ " Run './gradlew $project.path:dependencies --configuration $conf.name' "
|
|
||||||
+ "to diagnose")
|
|
||||||
}
|
|
||||||
result.selected.dependencies.each {
|
|
||||||
// Category.CATEGORY_ATTRIBUTE is the inappropriate Attribute because it is "desugared".
|
|
||||||
// https://github.com/gradle/gradle/issues/8854
|
|
||||||
Attribute<String> category = Attribute.of('org.gradle.category', String)
|
|
||||||
if (it.resolvedVariant.attributes.getAttribute(category) != Category.LIBRARY)
|
|
||||||
return
|
|
||||||
queue.add(new DepAndParents(
|
|
||||||
dep: it, parents: depAndParents.parents + [artifact + ":" + version]))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
repositories {
|
repositories {
|
||||||
mavenCentral()
|
mavenCentral()
|
||||||
google()
|
google()
|
||||||
|
|
@ -546,34 +485,4 @@ configurations {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Checks every dependency in the version catalog to see if there is a newer
|
tasks.register('checkForUpdates', CheckForUpdatesTask, project.configurations.checkForUpdates, "libs")
|
||||||
// version available. The 'checkForUpdates' configuration restricts the
|
|
||||||
// versions considered.
|
|
||||||
tasks.register('checkForUpdates') {
|
|
||||||
doLast {
|
|
||||||
def updateConf = project.configurations.checkForUpdates
|
|
||||||
updateConf.setVisible(false)
|
|
||||||
updateConf.setTransitive(false)
|
|
||||||
def versionCatalog = project.extensions.getByType(VersionCatalogsExtension).named("libs")
|
|
||||||
versionCatalog.libraryAliases.each { name ->
|
|
||||||
def dep = versionCatalog.findLibrary(name).get().get()
|
|
||||||
|
|
||||||
def oldConf = updateConf.copy()
|
|
||||||
def oldDep = project.dependencies.create(
|
|
||||||
group: dep.group, name: dep.name, version: dep.versionConstraint, classifier: 'pom')
|
|
||||||
oldConf.dependencies.add(oldDep)
|
|
||||||
def oldResolved = oldConf.resolvedConfiguration.resolvedArtifacts.iterator().next()
|
|
||||||
|
|
||||||
def newConf = updateConf.copy()
|
|
||||||
def newDep = project.dependencies.create(
|
|
||||||
group: dep.group, name: dep.name, version: '+', classifier: 'pom')
|
|
||||||
newConf.dependencies.add(newDep)
|
|
||||||
def newResolved = newConf.resolvedConfiguration.resolvedArtifacts.iterator().next()
|
|
||||||
if (oldResolved != newResolved) {
|
|
||||||
def oldId = oldResolved.id.componentIdentifier
|
|
||||||
def newId = newResolved.id.componentIdentifier
|
|
||||||
println("libs.${name} = ${newId.group}:${newId.module} ${oldId.version} -> ${newId.version}")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
tasks.withType(JavaCompile).configureEach {
|
||||||
|
it.options.compilerArgs += [
|
||||||
|
"-Xlint:all",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,131 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2023 The gRPC Authors
|
||||||
|
*
|
||||||
|
* Licensed 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 io.grpc.gradle;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.LinkedHashSet;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
import javax.inject.Inject;
|
||||||
|
import org.gradle.api.DefaultTask;
|
||||||
|
import org.gradle.api.artifacts.Configuration;
|
||||||
|
import org.gradle.api.artifacts.Dependency;
|
||||||
|
import org.gradle.api.artifacts.ModuleVersionIdentifier;
|
||||||
|
import org.gradle.api.artifacts.VersionCatalog;
|
||||||
|
import org.gradle.api.artifacts.VersionCatalogsExtension;
|
||||||
|
import org.gradle.api.artifacts.result.ResolvedComponentResult;
|
||||||
|
import org.gradle.api.artifacts.result.ResolvedDependencyResult;
|
||||||
|
import org.gradle.api.provider.Provider;
|
||||||
|
import org.gradle.api.tasks.Input;
|
||||||
|
import org.gradle.api.tasks.Nested;
|
||||||
|
import org.gradle.api.tasks.TaskAction;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks every dependency in the version catalog to see if there is a newer version available. The
|
||||||
|
* passed configuration restricts the versions considered.
|
||||||
|
*/
|
||||||
|
public abstract class CheckForUpdatesTask extends DefaultTask {
|
||||||
|
private final Set<Library> libraries;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
public CheckForUpdatesTask(Configuration updateConf, String catalog) {
|
||||||
|
updateConf.setVisible(false);
|
||||||
|
updateConf.setTransitive(false);
|
||||||
|
VersionCatalog versionCatalog = getProject().getExtensions().getByType(VersionCatalogsExtension.class).named(catalog);
|
||||||
|
Set<Library> libraries = new LinkedHashSet<Library>();
|
||||||
|
for (String name : versionCatalog.getLibraryAliases()) {
|
||||||
|
org.gradle.api.artifacts.MinimalExternalModuleDependency dep = versionCatalog.findLibrary(name).get().get();
|
||||||
|
|
||||||
|
Configuration oldConf = updateConf.copy();
|
||||||
|
Dependency oldDep = getProject().getDependencies().create(
|
||||||
|
depMap(dep.getGroup(), dep.getName(), dep.getVersionConstraint().toString(), "pom"));
|
||||||
|
oldConf.getDependencies().add(oldDep);
|
||||||
|
|
||||||
|
Configuration newConf = updateConf.copy();
|
||||||
|
Dependency newDep = getProject().getDependencies().create(
|
||||||
|
depMap(dep.getGroup(), dep.getName(), "+", "pom"));
|
||||||
|
newConf.getDependencies().add(newDep);
|
||||||
|
|
||||||
|
libraries.add(new Library(
|
||||||
|
name,
|
||||||
|
oldConf.getIncoming().getResolutionResult().getRootComponent(),
|
||||||
|
newConf.getIncoming().getResolutionResult().getRootComponent()));
|
||||||
|
}
|
||||||
|
this.libraries = Collections.unmodifiableSet(libraries);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Map<String, String> depMap(
|
||||||
|
String group, String name, String version, String classifier) {
|
||||||
|
Map<String, String> map = new HashMap<>();
|
||||||
|
map.put("group", group);
|
||||||
|
map.put("name", name);
|
||||||
|
map.put("version", version);
|
||||||
|
map.put("classifier", classifier);
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nested
|
||||||
|
protected Set<Library> getLibraries() {
|
||||||
|
return libraries;
|
||||||
|
}
|
||||||
|
|
||||||
|
@TaskAction
|
||||||
|
public void checkForUpdates() {
|
||||||
|
for (Library lib : libraries) {
|
||||||
|
String name = lib.getName();
|
||||||
|
ModuleVersionIdentifier oldId = ((ResolvedDependencyResult) lib.getOldResult().get()
|
||||||
|
.getDependencies().iterator().next()).getSelected().getModuleVersion();
|
||||||
|
ModuleVersionIdentifier newId = ((ResolvedDependencyResult) lib.getNewResult().get()
|
||||||
|
.getDependencies().iterator().next()).getSelected().getModuleVersion();
|
||||||
|
if (oldId != newId) {
|
||||||
|
System.out.println(String.format(
|
||||||
|
"libs.%s = %s:%s %s -> %s",
|
||||||
|
name, newId.getGroup(), newId.getModule(), oldId.getVersion(), newId.getVersion()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final class Library {
|
||||||
|
private final String name;
|
||||||
|
private final Provider<ResolvedComponentResult> oldResult;
|
||||||
|
private final Provider<ResolvedComponentResult> newResult;
|
||||||
|
|
||||||
|
public Library(
|
||||||
|
String name, Provider<ResolvedComponentResult> oldResult,
|
||||||
|
Provider<ResolvedComponentResult> newResult) {
|
||||||
|
this.name = name;
|
||||||
|
this.oldResult = oldResult;
|
||||||
|
this.newResult = newResult;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Input
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Input
|
||||||
|
public Provider<ResolvedComponentResult> getOldResult() {
|
||||||
|
return oldResult;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Input
|
||||||
|
public Provider<ResolvedComponentResult> getNewResult() {
|
||||||
|
return newResult;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,66 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2023 The gRPC Authors
|
||||||
|
*
|
||||||
|
* Licensed 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 io.grpc.gradle;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.Enumeration;
|
||||||
|
import java.util.jar.JarEntry;
|
||||||
|
import java.util.jar.JarFile;
|
||||||
|
import org.gradle.api.DefaultTask;
|
||||||
|
import org.gradle.api.file.ConfigurableFileCollection;
|
||||||
|
import org.gradle.api.provider.Property;
|
||||||
|
import org.gradle.api.tasks.Classpath;
|
||||||
|
import org.gradle.api.tasks.Input;
|
||||||
|
import org.gradle.api.tasks.TaskAction;
|
||||||
|
import org.gradle.api.tasks.TaskExecutionException;
|
||||||
|
|
||||||
|
/** Verifies all class files within jar files are in a specified Java package. */
|
||||||
|
public abstract class CheckPackageLeakageTask extends DefaultTask {
|
||||||
|
public CheckPackageLeakageTask() {
|
||||||
|
// Fake output for UP-TO-DATE checking
|
||||||
|
getOutputs().file(getProject().getLayout().getBuildDirectory().file("tmp/" + getName()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Classpath
|
||||||
|
abstract ConfigurableFileCollection getFiles();
|
||||||
|
|
||||||
|
@Input
|
||||||
|
abstract Property<String> getPrefix();
|
||||||
|
|
||||||
|
@TaskAction
|
||||||
|
public void checkLeakage() throws IOException {
|
||||||
|
String jarEntryPrefixName = getPrefix().get().replace('.', '/');
|
||||||
|
boolean packageLeakDetected = false;
|
||||||
|
for (File jar : getFiles()) {
|
||||||
|
try (JarFile jf = new JarFile(jar)) {
|
||||||
|
for (Enumeration<JarEntry> e = jf.entries(); e.hasMoreElements(); ) {
|
||||||
|
JarEntry entry = e.nextElement();
|
||||||
|
if (entry.getName().endsWith(".class")
|
||||||
|
&& !entry.getName().startsWith(jarEntryPrefixName)) {
|
||||||
|
packageLeakDetected = true;
|
||||||
|
System.out.println("WARNING: package leaked, may need relocation: " + entry.getName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (packageLeakDetected) {
|
||||||
|
throw new TaskExecutionException(this,
|
||||||
|
new IllegalStateException("Resource leakage detected!"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,137 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2023 The gRPC Authors
|
||||||
|
*
|
||||||
|
* Licensed 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 io.grpc.gradle;
|
||||||
|
|
||||||
|
import java.util.ArrayDeque;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Queue;
|
||||||
|
import java.util.Set;
|
||||||
|
import org.gradle.api.DefaultTask;
|
||||||
|
import org.gradle.api.artifacts.Configuration;
|
||||||
|
import org.gradle.api.artifacts.ModuleVersionIdentifier;
|
||||||
|
import org.gradle.api.artifacts.component.ModuleComponentSelector;
|
||||||
|
import org.gradle.api.artifacts.component.ProjectComponentSelector;
|
||||||
|
import org.gradle.api.artifacts.result.DependencyResult;
|
||||||
|
import org.gradle.api.artifacts.result.ResolvedComponentResult;
|
||||||
|
import org.gradle.api.artifacts.result.ResolvedDependencyResult;
|
||||||
|
import org.gradle.api.attributes.Attribute;
|
||||||
|
import org.gradle.api.attributes.Category;
|
||||||
|
import org.gradle.api.provider.Property;
|
||||||
|
import org.gradle.api.tasks.Input;
|
||||||
|
import org.gradle.api.tasks.TaskAction;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Verifies that Maven would select the same versions as Gradle selected. This is essentially the
|
||||||
|
* same as if we used Maven Enforcer's requireUpperBoundDeps in a Maven build. Gradle selects the
|
||||||
|
* upperBound, so if Maven selects a different version there is a downgrade.
|
||||||
|
*/
|
||||||
|
public abstract class RequireUpperBoundDepsMatchTask extends DefaultTask {
|
||||||
|
private final String projectPath;
|
||||||
|
private final String projectVersion;
|
||||||
|
|
||||||
|
public RequireUpperBoundDepsMatchTask() {
|
||||||
|
projectPath = getProject().getPath();
|
||||||
|
projectVersion = getProject().getVersion().toString();
|
||||||
|
|
||||||
|
// Fake output for UP-TO-DATE checking
|
||||||
|
getOutputs().file(getProject().getLayout().getBuildDirectory().file("tmp/" + getName()));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setConfiguration(Configuration conf) {
|
||||||
|
getConfigurationName().set(conf.getName());
|
||||||
|
getRoot().set(conf.getIncoming().getResolutionResult().getRootComponent());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Input
|
||||||
|
abstract Property<String> getConfigurationName();
|
||||||
|
|
||||||
|
@Input
|
||||||
|
abstract Property<ResolvedComponentResult> getRoot();
|
||||||
|
|
||||||
|
@TaskAction
|
||||||
|
public void checkDeps() {
|
||||||
|
// Category.CATEGORY_ATTRIBUTE is the inappropriate Attribute because it is "desugared".
|
||||||
|
// https://github.com/gradle/gradle/issues/8854
|
||||||
|
Attribute<String> category = Attribute.of("org.gradle.category", String.class);
|
||||||
|
|
||||||
|
// Breadth-first search like Maven for dependency resolution. Check and Maven and Gradle would
|
||||||
|
// select the same version.
|
||||||
|
Queue<DepAndParents> queue = new ArrayDeque<>();
|
||||||
|
for (DependencyResult dep : getRoot().get().getDependencies()) {
|
||||||
|
queue.add(new DepAndParents(dep, null, projectPath));
|
||||||
|
}
|
||||||
|
Set<String> found = new HashSet<>();
|
||||||
|
while (!queue.isEmpty()) {
|
||||||
|
DepAndParents depAndParents = queue.remove();
|
||||||
|
ResolvedDependencyResult result = (ResolvedDependencyResult) depAndParents.dep;
|
||||||
|
// Only libraries are "deps" in the typical sense, and non-libraries might not have versions.
|
||||||
|
if (result.getResolvedVariant().getAttributes().getAttribute(category)
|
||||||
|
!= Category.LIBRARY)
|
||||||
|
return;
|
||||||
|
|
||||||
|
ModuleVersionIdentifier id = result.getSelected().getModuleVersion();
|
||||||
|
String artifact = id.getGroup() + ":" + id.getName();
|
||||||
|
if (found.contains(artifact))
|
||||||
|
continue;
|
||||||
|
found.add(artifact);
|
||||||
|
String mavenVersion;
|
||||||
|
if (result.getRequested() instanceof ProjectComponentSelector) {
|
||||||
|
// Assume all projects use the same version.
|
||||||
|
mavenVersion = projectVersion;
|
||||||
|
} else {
|
||||||
|
mavenVersion = ((ModuleComponentSelector) result.getRequested()).getVersion();
|
||||||
|
}
|
||||||
|
String gradleVersion = id.getVersion();
|
||||||
|
if (!mavenVersion.equals(gradleVersion) && !mavenVersion.equals("[" + gradleVersion + "]")) {
|
||||||
|
throw new RuntimeException(String.format(
|
||||||
|
"Maven version skew: %s (%s != %s) Bad version dependency path: %s"
|
||||||
|
+ " Run './gradlew %s:dependencies --configuration %s' to diagnose",
|
||||||
|
artifact, mavenVersion, gradleVersion, depAndParents.getParents(),
|
||||||
|
projectPath, getConfigurationName().get()));
|
||||||
|
}
|
||||||
|
for (DependencyResult dep : result.getSelected().getDependencies()) {
|
||||||
|
queue.add(new DepAndParents(dep, depAndParents, artifact + ":" + mavenVersion));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static final class DepAndParents {
|
||||||
|
final DependencyResult dep;
|
||||||
|
final DepAndParents parent;
|
||||||
|
final String parentName;
|
||||||
|
|
||||||
|
public DepAndParents(DependencyResult dep, DepAndParents parent, String parentName) {
|
||||||
|
this.dep = dep;
|
||||||
|
this.parent = parent;
|
||||||
|
this.parentName = parentName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<String> getParents() {
|
||||||
|
List<String> parents = new ArrayList<>();
|
||||||
|
DepAndParents element = this;
|
||||||
|
while (element != null) {
|
||||||
|
parents.add(element.parentName);
|
||||||
|
element = element.parent;
|
||||||
|
}
|
||||||
|
Collections.reverse(parents);
|
||||||
|
return parents;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import java.util.jar.JarFile
|
import io.grpc.gradle.CheckPackageLeakageTask;
|
||||||
|
|
||||||
plugins {
|
plugins {
|
||||||
id "java"
|
id "java"
|
||||||
|
|
@ -193,29 +193,9 @@ tasks.named("shadowJar").configure {
|
||||||
exclude "**/*.proto"
|
exclude "**/*.proto"
|
||||||
}
|
}
|
||||||
|
|
||||||
def checkPackageLeakage = tasks.register("checkPackageLeakage") {
|
def checkPackageLeakage = tasks.register("checkPackageLeakage", CheckPackageLeakageTask) {
|
||||||
inputs.files(shadowJar).withNormalizer(CompileClasspathNormalizer)
|
files.from tasks.named('shadowJar')
|
||||||
outputs.file("${buildDir}/tmp/${name}") // Fake output for UP-TO-DATE checking
|
prefix = prefixName
|
||||||
doLast {
|
|
||||||
def jarEntryPrefixName = prefixName.replaceAll('\\.', '/')
|
|
||||||
shadowJar.outputs.getFiles().each { jar ->
|
|
||||||
def package_leak_detected = false
|
|
||||||
JarFile jf = new JarFile(jar)
|
|
||||||
jf.entries().each { entry ->
|
|
||||||
if (entry.name.endsWith(".class") && !entry.name.startsWith(
|
|
||||||
jarEntryPrefixName)) {
|
|
||||||
package_leak_detected = true
|
|
||||||
println "WARNING: package leaked, may need relocation: " +
|
|
||||||
entry.name
|
|
||||||
}
|
|
||||||
}
|
|
||||||
jf.close()
|
|
||||||
if (package_leak_detected) {
|
|
||||||
throw new TaskExecutionException(shadowJar,
|
|
||||||
new IllegalStateException("Resource leakage detected!"))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
tasks.named("test").configure {
|
tasks.named("test").configure {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue