Skip to content

Commit a76cbcc

Browse files
committed
Merge pull request #14 from rspieldenner/changeresolve
bugfixes related to use with dependencyLock and other modifications t…
2 parents 98053f6 + 0c02c9e commit a76cbcc

File tree

8 files changed

+304
-63
lines changed

8 files changed

+304
-63
lines changed

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
1.2.1 / 2016/04/19
2+
==================
3+
- BUGFIX: Make sure resolutionRules configuration can be locked by nebula.dependency-lock
4+
- BUGFIX: Allow other changes to configurations.all and associated resolutionStrategy
5+
16
1.2.0 / 2016/04/11
27
==================
38
- Allow opt out of rules for shared company wide rules that apply to your project, e.g. there is a common align rule for a:foo and a:bar and you produce them

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ The [Blacklist Plugin](https://github.com/nebula-plugins/gradle-blacklist-plugin
2121
}
2222
2323
dependencies {
24-
classpath 'com.netflix.nebula:gradle-resolution-rules-plugin:1.2.0'
24+
classpath 'com.netflix.nebula:gradle-resolution-rules-plugin:1.2.1'
2525
}
2626
}
2727
@@ -32,7 +32,7 @@ Or using the Gradle plugin portal:
3232

3333
```groovy
3434
plugins {
35-
id 'nebula.resolution-rules' version '1.2.0'
35+
id 'nebula.resolution-rules' version '1.2.1'
3636
}
3737
```
3838

build.gradle

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,11 @@ facets {
5757
}
5858
}
5959

60+
tasks.withType(Test) {
61+
maxHeapSize = '512m'
62+
jvmArgs '-XX:MaxPermSize=128m'
63+
}
64+
6065
apply from: 'gradle/idea.gradle'
6166
apply from: 'https://raw.githubusercontent.com/nebula-plugins/nebula-core/59c9e15f561372a8a72bbe13e4fbb114d0ef16f8/common.gradle'
6267

src/functionalTest/groovy/nebula/plugin/resolutionrules/AlignRulesPluginInteractionSpec.groovy

Lines changed: 147 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,17 @@
1414
* limitations under the License.
1515
*
1616
*/
17-
1817
package nebula.plugin.resolutionrules
1918

2019
import nebula.test.IntegrationSpec
2120
import nebula.test.dependencies.DependencyGraphBuilder
2221
import nebula.test.dependencies.GradleDependencyGenerator
2322

23+
import java.util.jar.Attributes
24+
import java.util.jar.JarEntry
25+
import java.util.jar.JarOutputStream
26+
import java.util.jar.Manifest
27+
2428
class AlignRulesPluginInteractionSpec extends IntegrationSpec {
2529
def 'alignment interaction with dependency-recommender'() {
2630
def graph = new DependencyGraphBuilder()
@@ -301,7 +305,6 @@ class AlignRulesPluginInteractionSpec extends IntegrationSpec {
301305
result.standardOutput.contains '\\--- test.a:b: -> 1.2.1\n'
302306
}
303307

304-
@spock.lang.Ignore
305308
def 'cycle like behavior'() {
306309
def graph = new DependencyGraphBuilder()
307310
.addModule('test.nebula:c:1.42.2')
@@ -322,11 +325,13 @@ class AlignRulesPluginInteractionSpec extends IntegrationSpec {
322325

323326
buildFile << """\
324327
buildscript {
325-
repositories { jcenter() }
328+
repositories {
329+
jcenter()
330+
}
326331
327332
dependencies {
328333
classpath 'com.netflix.nebula:nebula-publishing-plugin:4.4.4'
329-
classpath 'com.netflix.nebula:gradle-extra-configurations-plugin:3.0.3'
334+
classpath 'com.netflix.nebula:gradle-extra-configurations-plugin:3.1.0'
330335
}
331336
}
332337
subprojects {
@@ -366,4 +371,142 @@ class AlignRulesPluginInteractionSpec extends IntegrationSpec {
366371
then:
367372
noExceptionThrown()
368373
}
374+
375+
def 'able to lock rules'() {
376+
def graph = new DependencyGraphBuilder()
377+
.addModule('test.nebula:a:1.41.5')
378+
.addModule('test.nebula:a:1.42.2')
379+
.addModule('test.nebula:b:1.41.5')
380+
.addModule('test.nebula:b:1.42.2')
381+
.build()
382+
def mavenrepo = new GradleDependencyGenerator(graph, "$projectDir/testrepogen")
383+
mavenrepo.generateTestMavenRepo()
384+
385+
def rulesFolder = new File(projectDir, 'rules')
386+
rulesFolder.mkdirs()
387+
def rulesJsonFile = new File(rulesFolder, 'rules.json')
388+
389+
rulesJsonFile << '''\
390+
{
391+
"deny": [], "reject": [], "substitute": [], "replace": [],
392+
"align": [
393+
{
394+
"name": "testNebula",
395+
"group": "test.nebula",
396+
"reason": "Align test.nebula dependencies",
397+
"author": "Example Person <person@example.org>",
398+
"date": "2016-03-17T20:21:20.368Z"
399+
}
400+
]
401+
}
402+
'''.stripIndent()
403+
404+
def mavenForRules = new File(projectDir, 'repo')
405+
mavenForRules.mkdirs()
406+
def locked = new File(mavenForRules, 'test/rules/resolution-rules/1.0.0')
407+
locked.mkdirs()
408+
createRulesJar([rulesFolder], projectDir, new File(locked, 'resolution-rules-1.0.0.jar'))
409+
createPom('test.rules', 'resolution-rules', '1.0.0', locked)
410+
411+
rulesJsonFile.text = '''\
412+
{
413+
"deny": [], "reject": [], "substitute": [], "replace": [], "align": []
414+
}
415+
'''.stripIndent()
416+
def newer = new File(mavenForRules, 'test/rules/resolution-rules/1.1.0')
417+
newer.mkdirs()
418+
createRulesJar([rulesFolder], projectDir, new File(newer, 'resolution-rules-1.1.0.jar'))
419+
createPom('test.rules', 'resolution-rules', '1.1.0', newer)
420+
421+
def dependencyLock = new File(projectDir, 'dependencies.lock')
422+
423+
dependencyLock << '''\
424+
{
425+
"resolutionRules": {
426+
"test.rules:resolution-rules": { "locked": "1.0.0" }
427+
}
428+
}
429+
'''.stripIndent()
430+
431+
buildFile << """\
432+
buildscript {
433+
repositories { jcenter() }
434+
dependencies {
435+
classpath 'com.netflix.nebula:gradle-dependency-lock-plugin:4.2.0'
436+
}
437+
}
438+
439+
${applyPlugin(ResolutionRulesPlugin)}
440+
apply plugin: 'nebula.dependency-lock'
441+
apply plugin: 'java'
442+
443+
repositories {
444+
${mavenrepo.mavenRepositoryBlock}
445+
maven { url '${mavenForRules.absolutePath}' }
446+
}
447+
448+
dependencies {
449+
resolutionRules 'test.rules:resolution-rules:1.+'
450+
compile 'test.nebula:a:1.41.5'
451+
compile 'test.nebula:b:1.42.2'
452+
}
453+
""".stripIndent()
454+
455+
when:
456+
def results = runTasksSuccessfully('dependencies', '--configuration', 'resolutionRules')
457+
458+
then:
459+
results.standardOutput.contains '\\--- test.rules:resolution-rules:1.+ -> 1.0.0\n'
460+
461+
when:
462+
results = runTasksSuccessfully('dependencies', '--configuration', 'compile')
463+
464+
then:
465+
results.standardOutput.contains '+--- test.nebula:a:1.41.5 -> 1.42.2\n'
466+
results.standardOutput.contains '\\--- test.nebula:b:1.42.2\n'
467+
}
468+
469+
private createRulesJar(Collection<File> files, File unneededRoot, File destination) {
470+
Manifest manifest = new Manifest()
471+
manifest.getMainAttributes().put(Attributes.Name.MANIFEST_VERSION, '1.0')
472+
JarOutputStream target = new JarOutputStream(new FileOutputStream(destination), manifest)
473+
files.each { add(it, unneededRoot, target) }
474+
target.close()
475+
}
476+
477+
private createPom(String group, String name, String version, File dir) {
478+
def pom = new File(dir, "${name}-${version}.pom")
479+
pom.text = """\
480+
<?xml version="1.0" encoding="UTF-8"?>
481+
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
482+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
483+
<modelVersion>4.0.0</modelVersion>
484+
<groupId>${group}</groupId>
485+
<artifactId>${name}</artifactId>
486+
<version>${version}</version>
487+
</project>
488+
""".stripIndent()
489+
}
490+
491+
private void add(File source, File unneededRoot, JarOutputStream target) throws IOException
492+
{
493+
def prefix = "${unneededRoot.path}/"
494+
if (source.isDirectory()) {
495+
String dirName = source.path - prefix
496+
if (!dirName.endsWith('/')) {
497+
dirName += '/'
498+
}
499+
def entry = new JarEntry(dirName)
500+
target.putNextEntry(entry)
501+
target.closeEntry()
502+
source.listFiles().each { nested ->
503+
add(nested, unneededRoot, target)
504+
}
505+
} else {
506+
def entry = new JarEntry(source.path - prefix)
507+
target.putNextEntry(entry)
508+
target << source.bytes
509+
target.closeEntry()
510+
}
511+
}
369512
}

src/functionalTest/groovy/nebula/plugin/resolutionrules/AlignRulesSpec.groovy

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -710,4 +710,69 @@ class AlignRulesSpec extends IntegrationSpec {
710710
result.standardOutput.contains '+--- test.nebula:a:1.0.0\n'
711711
result.standardOutput.contains '\\--- test.nebula:b:0.15.0\n'
712712
}
713+
714+
def 'can add additional resolution rules outside of plugin'() {
715+
def graph = new DependencyGraphBuilder()
716+
.addModule('test.nebula:a:1.0.0')
717+
.addModule('test.nebula:a:0.15.0')
718+
.addModule('test.nebula:b:1.0.0')
719+
.addModule('test.nebula:b:0.15.0')
720+
.addModule('test.example:c:0.1.0')
721+
.addModule('test.example:c:0.2.0')
722+
.addModule('test:x:1.0.0')
723+
.addModule('test:x:1.0.1')
724+
.addModule('test:y:1.0.0')
725+
.addModule('test:y:1.0.1')
726+
.build()
727+
File mavenrepo = new GradleDependencyGenerator(graph, "${projectDir}/testrepogen").generateTestMavenRepo()
728+
729+
rulesJsonFile << '''\
730+
{
731+
"deny": [], "reject": [], "substitute": [], "replace": [],
732+
"align": [
733+
{
734+
"name": "testNebula",
735+
"group": "test.nebula",
736+
"reason": "Align test.nebula dependencies",
737+
"author": "Example Person <person@example.org>",
738+
"date": "2016-03-17T20:21:20.368Z"
739+
}
740+
]
741+
}
742+
'''.stripIndent()
743+
744+
buildFile << """\
745+
repositories {
746+
maven { url '${mavenrepo.absolutePath}' }
747+
}
748+
configurations.all {
749+
resolutionStrategy {
750+
force 'test.example:c:0.1.0'
751+
eachDependency { details ->
752+
if (details.requested.group == 'test') {
753+
details.useTarget group: details.requested.group, name: details.requested.name, version: '1.0.0'
754+
}
755+
}
756+
}
757+
}
758+
dependencies {
759+
compile 'test.nebula:a:1.0.0'
760+
compile 'test.nebula:b:0.15.0'
761+
compile 'test.example:c:latest.release'
762+
compile 'test:x:1.+'
763+
compile 'test:y:1.+'
764+
}
765+
""".stripIndent()
766+
767+
when:
768+
def result = runTasksSuccessfully('dependencies', '--configuration', 'compile')
769+
770+
then:
771+
result.standardOutput.contains '+--- test.nebula:a:1.0.0\n'
772+
result.standardOutput.contains '+--- test.nebula:b:0.15.0 -> 1.0.0\n'
773+
result.standardOutput.contains '+--- test.example:c:latest.release -> 0.1.0\n'
774+
result.standardOutput.contains '+--- test:x:1.+ -> 1.0.0\n'
775+
result.standardOutput.contains '\\--- test:y:1.+ -> 1.0.0\n'
776+
777+
}
713778
}

src/functionalTest/groovy/nebula/plugin/resolutionrules/PluginFunctionalTest.groovy

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -118,9 +118,9 @@ class PluginFunctionalTest extends IntegrationSpec {
118118

119119
def 'warning logged when configuration has been resolved'() {
120120
given:
121-
buildFile << """
122-
configurations.compile.resolvedConfiguration
123-
""".stripIndent()
121+
buildFile << """\
122+
configurations.compile.resolve()
123+
""".stripIndent()
124124

125125
when:
126126
def result = runTasksSuccessfully()

src/main/groovy/nebula/plugin/resolutionrules/ResolutionRulesPlugin.groovy

Lines changed: 37 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -20,28 +20,61 @@ import groovy.json.JsonSlurper
2020
import org.gradle.api.Plugin
2121
import org.gradle.api.Project
2222
import org.gradle.api.artifacts.Configuration
23+
import org.gradle.api.artifacts.ResolutionStrategy
2324
import org.slf4j.Logger
2425
import org.slf4j.LoggerFactory
2526

2627
import java.util.zip.ZipEntry
2728
import java.util.zip.ZipFile
2829

2930
class ResolutionRulesPlugin implements Plugin<Project> {
31+
Project project
3032
Logger logger = LoggerFactory.getLogger(ResolutionRulesPlugin)
3133
String configurationName = "resolutionRules"
34+
Rules rules
3235

3336
public void apply(Project project) {
37+
this.project = project
3438
Configuration configuration = project.configurations.create(configurationName)
3539
def extension = project.extensions.create('nebulaResolutionRules', NebulaResolutionRulesExtension)
36-
project.afterEvaluate {
37-
Rules rules = rulesFromConfiguration(configuration)
38-
applyRules(rules, project, extension)
40+
41+
project.gradle.projectsEvaluated {
42+
project.configurations.all{ Configuration config ->
43+
if (config.name == configurationName) {
44+
return
45+
}
46+
if (config.state != Configuration.State.UNRESOLVED) {
47+
logger.warn("Configuration '{}' has been resolved. Dependency resolution rules will not be applied", config.name)
48+
return
49+
}
50+
config.resolutionStrategy { ResolutionStrategy rs ->
51+
getRules().configurationRules().each { ConfigurationRule rule ->
52+
rule.apply(config)
53+
}
54+
getRules().resolutionRules().each { ResolutionRule rule ->
55+
rule.apply(rs)
56+
}
57+
getRules().projectConfigurationRules().each { ProjectConfigurationRule rule ->
58+
rule.apply(project, rs, config, extension)
59+
}
60+
}
61+
62+
}
63+
getRules().projectRules().each { ProjectRule rule -> rule.apply(project) }
3964
}
4065
}
4166

67+
Rules getRules() {
68+
if (!rules) {
69+
rules = rulesFromConfiguration(project.configurations.getByName(configurationName))
70+
}
71+
72+
rules
73+
}
74+
4275
private Rules rulesFromConfiguration(Configuration configuration) {
4376
List<Rules> rules = new ArrayList<Rules>();
44-
Set<File> files = configuration.resolve()
77+
Set<File> files = configuration.copyRecursive().resolve()
4578
if (files.isEmpty()) {
4679
logger.warn("No resolution rules have been added to the '{}' configuration", configuration.name)
4780
}
@@ -103,21 +136,4 @@ class ResolutionRulesPlugin implements Plugin<Project> {
103136
List<AlignRule> align = rules.collectMany { it.align }.flatten() as List<AlignRule>
104137
return new Rules(replace: replace, substitute: substitute, reject: reject, deny: deny, align: align)
105138
}
106-
107-
private void applyRules(Rules rules, Project project, NebulaResolutionRulesExtension extension) {
108-
rules.projectRules().each { it.apply(project) }
109-
project.configurations.all({ configuration ->
110-
if (configuration.name == configurationName) {
111-
return
112-
}
113-
if (configuration.state != Configuration.State.UNRESOLVED) {
114-
logger.warn("Configuration '{}' has been resolved. Dependency resolution rules will not be applied", configuration.name)
115-
return
116-
}
117-
rules.configurationRules().each {
118-
it.apply(configuration)
119-
}
120-
rules.projectConfigurationRules().each { it.apply(project, configuration, extension) }
121-
})
122-
}
123139
}

0 commit comments

Comments
 (0)