Skip to content

Commit

Permalink
Merge pull request #420 from rpalcolea/minimize-project-excludes-tests
Browse files Browse the repository at this point in the history
Minimize - Excluding a project also excludes its dependencies
  • Loading branch information
johnrengelman authored Jan 20, 2019
2 parents 08a6a3c + e72c396 commit 27cfe4d
Show file tree
Hide file tree
Showing 5 changed files with 314 additions and 109 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
package com.github.jengelman.gradle.plugins.shadow.internal

import groovy.util.logging.Slf4j
import org.gradle.api.Project
import org.gradle.api.artifacts.Configuration
import org.gradle.api.artifacts.Dependency
import org.gradle.api.artifacts.ResolvedDependency
import org.gradle.api.file.FileCollection
import org.gradle.api.specs.Spec
import org.gradle.api.specs.Specs

@Slf4j
abstract class AbstractDependencyFilter implements DependencyFilter {
private final Project project

protected final List<Spec<? super ResolvedDependency>> includeSpecs = []
protected final List<Spec<? super ResolvedDependency>> excludeSpecs = []

AbstractDependencyFilter(Project project) {
assert project
this.project = project
}

abstract protected void resolve(Set<ResolvedDependency> dependencies,
Set<ResolvedDependency> includedDependencies,
Set<ResolvedDependency> excludedDependencies)

FileCollection resolve(Configuration configuration) {
Set<ResolvedDependency> includedDeps = []
Set<ResolvedDependency> excludedDeps = []
resolve(configuration.resolvedConfiguration.firstLevelModuleDependencies, includedDeps, excludedDeps)
return project.files(configuration.files) - project.files(excludedDeps.collect {
it.moduleArtifacts*.file
}.flatten())
}

FileCollection resolve(Collection<Configuration> configurations) {
configurations.collect {
resolve(it)
}.sum() as FileCollection ?: project.files()
}

/**
* Exclude dependencies that match the provided spec.
*
* @param spec
* @return
*/
DependencyFilter exclude(Spec<? super ResolvedDependency> spec) {
excludeSpecs << spec
return this
}

/**
* Include dependencies that match the provided spec.
*
* @param spec
* @return
*/
DependencyFilter include(Spec<? super ResolvedDependency> spec) {
includeSpecs << spec
return this
}

/**
* Create a spec that matches the provided project notation on group, name, and version
* @param notation
* @return
*/
Spec<? super ResolvedDependency> project(Map<String, ?> notation) {
dependency(project.dependencies.project(notation))
}

/**
* Create a spec that matches the default configuration for the provided project path on group, name, and version
*
* @param notation
* @return
*/
Spec<? super ResolvedDependency> project(String notation) {
dependency(project.dependencies.project(path: notation, configuration: 'default'))
}

/**
* Create a spec that matches dependencies using the provided notation on group, name, and version
* @param notation
* @return
*/
Spec<? super ResolvedDependency> dependency(Object notation) {
dependency(project.dependencies.create(notation))
}

/**
* Create a spec that matches the provided dependency on group, name, and version
* @param dependency
* @return
*/
Spec<? super ResolvedDependency> dependency(Dependency dependency) {
this.dependency({ ResolvedDependency it ->
(!dependency.group || it.moduleGroup.matches(dependency.group)) &&
(!dependency.name || it.moduleName.matches(dependency.name)) &&
(!dependency.version || it.moduleVersion.matches(dependency.version))
})
}

/**
* Create a spec that matches the provided closure
* @param spec
* @return
*/
Spec<? super ResolvedDependency> dependency(Closure spec) {
return Specs.<ResolvedDependency>convertClosureToSpec(spec)
}

protected boolean isIncluded(ResolvedDependency dependency) {
boolean include = includeSpecs.empty || includeSpecs.any { it.isSatisfiedBy(dependency) }
boolean exclude = !excludeSpecs.empty && excludeSpecs.any { it.isSatisfiedBy(dependency) }
return include && !exclude
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,114 +2,16 @@ package com.github.jengelman.gradle.plugins.shadow.internal

import groovy.util.logging.Slf4j
import org.gradle.api.Project
import org.gradle.api.artifacts.Configuration
import org.gradle.api.artifacts.Dependency
import org.gradle.api.artifacts.ResolvedDependency
import org.gradle.api.file.FileCollection
import org.gradle.api.specs.Spec
import org.gradle.api.specs.Specs

@Slf4j
class DefaultDependencyFilter implements DependencyFilter {

private final Project project

private final List<Spec<? super ResolvedDependency>> includeSpecs = []
private final List<Spec<? super ResolvedDependency>> excludeSpecs = []
class DefaultDependencyFilter extends AbstractDependencyFilter {

DefaultDependencyFilter(Project project) {
assert project
this.project = project
}

FileCollection resolve(Configuration configuration) {
Set<ResolvedDependency> includedDeps = []
Set<ResolvedDependency> excludedDeps = []
resolve(configuration.resolvedConfiguration.firstLevelModuleDependencies, includedDeps, excludedDeps)
return project.files(configuration.files) - project.files(excludedDeps.collect {
it.moduleArtifacts*.file
}.flatten())
}

FileCollection resolve(Collection<Configuration> configurations) {
configurations.collect {
resolve(it)
}.sum() as FileCollection ?: project.files()
}

/**
* Exclude dependencies that match the provided spec.
*
* @param spec
* @return
*/
DependencyFilter exclude(Spec<? super ResolvedDependency> spec) {
excludeSpecs << spec
return this
}

/**
* Include dependencies that match the provided spec.
*
* @param spec
* @return
*/
DependencyFilter include(Spec<? super ResolvedDependency> spec) {
includeSpecs << spec
return this
}

/**
* Create a spec that matches the provided project notation on group, name, and version
* @param notation
* @return
*/
Spec<? super ResolvedDependency> project(Map<String, ?> notation) {
dependency(project.dependencies.project(notation))
}

/**
* Create a spec that matches the default configuration for the provided project path on group, name, and version
*
* @param notation
* @return
*/
Spec<? super ResolvedDependency> project(String notation) {
dependency(project.dependencies.project(path: notation, configuration: 'default'))
super(project)
}

/**
* Create a spec that matches dependencies using the provided notation on group, name, and version
* @param notation
* @return
*/
Spec<? super ResolvedDependency> dependency(Object notation) {
dependency(project.dependencies.create(notation))
}

/**
* Create a spec that matches the provided dependency on group, name, and version
* @param dependency
* @return
*/
Spec<? super ResolvedDependency> dependency(Dependency dependency) {
this.dependency({ ResolvedDependency it ->
(!dependency.group || it.moduleGroup.matches(dependency.group)) &&
(!dependency.name || it.moduleName.matches(dependency.name)) &&
(!dependency.version || it.moduleVersion.matches(dependency.version))
})
}

/**
* Create a spec that matches the provided closure
* @param spec
* @return
*/
Spec<? super ResolvedDependency> dependency(Closure spec) {
return Specs.<ResolvedDependency>convertClosureToSpec(spec)
}


@Override
protected void resolve(Set<ResolvedDependency> dependencies,
Set<ResolvedDependency> includedDependencies,
Set<ResolvedDependency> excludedDependencies) {
Expand All @@ -120,9 +22,4 @@ class DefaultDependencyFilter implements DependencyFilter {
}
}

protected boolean isIncluded(ResolvedDependency dependency) {
boolean include = includeSpecs.empty || includeSpecs.any { it.isSatisfiedBy(dependency) }
boolean exclude = !excludeSpecs.empty && excludeSpecs.any { it.isSatisfiedBy(dependency) }
return include && !exclude
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package com.github.jengelman.gradle.plugins.shadow.internal

import groovy.util.logging.Slf4j
import org.gradle.api.Project
import org.gradle.api.artifacts.ResolvedDependency

@Slf4j
class MinimizeDependencyFilter extends AbstractDependencyFilter {

MinimizeDependencyFilter(Project project) {
super(project)
}

@Override
protected void resolve(Set<ResolvedDependency> dependencies,
Set<ResolvedDependency> includedDependencies,
Set<ResolvedDependency> excludedDependencies) {

dependencies.each {
if (isIncluded(it) && !isParentExcluded(excludedDependencies, it) ? includedDependencies.add(it) : excludedDependencies.add(it)) {
resolve(it.children, includedDependencies, excludedDependencies)
}
}
}

private boolean isParentExcluded(Set<ResolvedDependency> excludedDependencies, ResolvedDependency dependency) {
excludedDependencies.any { dependency.parents.contains(it) }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,6 @@
import com.github.jengelman.gradle.plugins.shadow.transformers.ServiceFileTransformer;
import com.github.jengelman.gradle.plugins.shadow.transformers.Transformer;
import groovy.lang.MetaClass;
import java.io.File;
import java.util.Set;
import org.codehaus.groovy.runtime.InvokerHelper;
import org.gradle.api.Action;
import org.gradle.api.artifacts.Configuration;
Expand Down Expand Up @@ -45,7 +43,7 @@ public ShadowJar() {
super();
versionUtil = new GradleVersionUtil(getProject().getGradle().getGradleVersion());
dependencyFilter = new DefaultDependencyFilter(getProject());
dependencyFilterForMinimize = new DefaultDependencyFilter(getProject());
dependencyFilterForMinimize = new MinimizeDependencyFilter(getProject());
setManifest(new DefaultInheritManifest(getServices().get(FileResolver.class)));
transformers = new ArrayList<>();
relocators = new ArrayList<>();
Expand Down
Loading

0 comments on commit 27cfe4d

Please sign in to comment.