diff --git a/src/main/groovy/nebula/test/dependencies/Coordinate.groovy b/src/main/groovy/nebula/test/dependencies/Coordinate.groovy index 62fd231..d4d8596 100644 --- a/src/main/groovy/nebula/test/dependencies/Coordinate.groovy +++ b/src/main/groovy/nebula/test/dependencies/Coordinate.groovy @@ -22,9 +22,22 @@ class Coordinate { String group String artifact String version + String classifier + String extension @Override String toString() { - "${group}:${artifact}:${version}" + def sb = "${group}:${artifact}:${version}" + if (classifier) sb <<= ":${classifier}" + if (extension) sb <<= "@${extension}" + return sb + } + + public static Coordinate of(String s) { + def (substr, extension) = s.trim().tokenize("@") + + def (group, artifact, version, classifier) = substr.tokenize(':') + return new Coordinate( + group: group, artifact: artifact, version: version, classifier: classifier, extension: extension) } } diff --git a/src/main/groovy/nebula/test/dependencies/DependencyGraph.groovy b/src/main/groovy/nebula/test/dependencies/DependencyGraph.groovy index 8ae0d06..b3dbfe9 100644 --- a/src/main/groovy/nebula/test/dependencies/DependencyGraph.groovy +++ b/src/main/groovy/nebula/test/dependencies/DependencyGraph.groovy @@ -31,11 +31,10 @@ class DependencyGraph { } private DependencyGraphNode parseNode(String s) { - // Don't use tokenize, it'll make each character a possible delimeter, e.g. \t\n would tokenize on both + // Don't use tokenize, it'll make each character a possible delimiter, e.g. \t\n would tokenize on both // \t OR \n, not the combination of \t\n. def parts = s.split('->') - def (group, artifact, version) = parts[0].trim().tokenize(':') - def coordinate = new Coordinate(group: group, artifact: artifact, version: version) + def coordinate = Coordinate.of(parts[0]) def dependencies = (parts.size() > 1) ? parseDependencies(parts[1]) : [] new DependencyGraphNode(coordinate: coordinate, dependencies: dependencies) @@ -44,8 +43,7 @@ class DependencyGraph { private List parseDependencies(String s) { List dependencies = [] s.tokenize('|').each { String dependency -> - def (group, artifact, version) = dependency.trim().tokenize(':') - dependencies << new Coordinate(group: group, artifact: artifact, version: version) + dependencies << Coordinate.of(dependency) } dependencies diff --git a/src/main/groovy/nebula/test/dependencies/DependencyGraphBuilder.groovy b/src/main/groovy/nebula/test/dependencies/DependencyGraphBuilder.groovy index 582b3ca..b57977e 100644 --- a/src/main/groovy/nebula/test/dependencies/DependencyGraphBuilder.groovy +++ b/src/main/groovy/nebula/test/dependencies/DependencyGraphBuilder.groovy @@ -3,20 +3,30 @@ package nebula.test.dependencies class DependencyGraphBuilder { Map modules = [:] - DependencyGraphBuilder addModule(String coordinate) { - def (group, artifact, version) = coordinate.trim().tokenize(':') - addModule(group, artifact, version) + DependencyGraphBuilder addModule(String coordinateString) { + Coordinate coordinate = Coordinate.of(coordinateString) + modules[coordinate.toString()] = new DependencyGraphNode(coordinate: coordinate) + + this } DependencyGraphBuilder addModule(String group, String artifact, String version) { - String key = "${group}:${artifact}:${version}".toString() - modules[key] = new DependencyGraphNode(coordinate: new Coordinate(group: group, artifact: artifact, version: version)) + Coordinate coordinate = new Coordinate(group: group, artifact: artifact, version: version); + modules[coordinate.toString()] = new DependencyGraphNode(coordinate: coordinate) + + this + } + + DependencyGraphBuilder addModule(String group, String artifact, String version, String classifier, String extension) { + Coordinate coordinate = new Coordinate( + group: group, artifact: artifact, version: version, classifier: classifier, extension: extension); + modules[coordinate.toString()] = new DependencyGraphNode(coordinate: coordinate) this } DependencyGraphBuilder addModule(DependencyGraphNode node) { - modules[node.toString()] = node + modules[node.coordinate.toString()] = node node.dependencies.each { Coordinate dep -> if (!modules.containsKey(dep.toString())) { diff --git a/src/main/groovy/nebula/test/dependencies/DependencyGraphNode.groovy b/src/main/groovy/nebula/test/dependencies/DependencyGraphNode.groovy index 1dcbd9d..706b8a2 100644 --- a/src/main/groovy/nebula/test/dependencies/DependencyGraphNode.groovy +++ b/src/main/groovy/nebula/test/dependencies/DependencyGraphNode.groovy @@ -24,6 +24,6 @@ class DependencyGraphNode { @Override String toString() { - "${group}:${artifact}:${version}" + coordinate.toString() } } diff --git a/src/main/groovy/nebula/test/dependencies/GradleDependencyGenerator.groovy b/src/main/groovy/nebula/test/dependencies/GradleDependencyGenerator.groovy index c46092b..e01ae88 100644 --- a/src/main/groovy/nebula/test/dependencies/GradleDependencyGenerator.groovy +++ b/src/main/groovy/nebula/test/dependencies/GradleDependencyGenerator.groovy @@ -24,6 +24,9 @@ class GradleDependencyGenerator { apply plugin: 'ivy-publish' apply plugin: 'java' + task sourceJar(type: Jar) { + } + publishing { repositories { maven { @@ -43,11 +46,25 @@ class GradleDependencyGenerator { artifactId artifactName from components.java + + if (classifierName != null || extensionName != 'jar') { + artifact(sourceJar) { + classifier classifierName + extension extensionName + } + } } ivy(IvyPublication) { module artifactName from components.java + + if (classifierName != null || extensionName != 'jar') { + artifact(sourceJar) { + classifier classifierName + extension extensionName + } + } } } } @@ -156,6 +173,8 @@ class GradleDependencyGenerator { version = '${node.version}' ext { artifactName = '${node.artifact}' + extensionName = '${node.extension? node.extension: 'jar'}' + classifierName = ${node.classifier? "'${node.classifier}'": null} } """.stripIndent() + block.toString() } diff --git a/src/main/groovy/nebula/test/dependencies/ModuleBuilder.groovy b/src/main/groovy/nebula/test/dependencies/ModuleBuilder.groovy index a146aa6..459e6f9 100644 --- a/src/main/groovy/nebula/test/dependencies/ModuleBuilder.groovy +++ b/src/main/groovy/nebula/test/dependencies/ModuleBuilder.groovy @@ -5,23 +5,34 @@ class ModuleBuilder { List dependencies = [] ModuleBuilder(String coordinate) { - def (group, artifact, version) = coordinate.tokenize(':') - module = new Coordinate(group: group, artifact: artifact, version: version) + module = Coordinate.of(coordinate) } ModuleBuilder(String group, String artifact, String version) { module = new Coordinate(group: group, artifact: artifact, version: version) } + ModuleBuilder(String group, String artifact, String version, String classifier, String extension) { + module = new Coordinate( + group: group, artifact: artifact, version: version, classifier: classifier, extension: extension) + } + ModuleBuilder addDependency(String dependency) { - def (group, artifact, version) = dependency.tokenize(':') - dependencies << new Coordinate(group: group, artifact: artifact, version: version) + dependencies << Coordinate.of(dependency) this } ModuleBuilder addDependency(String group, String artifact, String version) { - dependencies << new Coordinate(group: group, artifact: artifact, version: version) + dependencies << new Coordinate( + group: group, artifact: artifact, version: version) + + this + } + + ModuleBuilder addDependency(String group, String artifact, String version, String classifier, String extension) { + dependencies << new Coordinate( + group: group, artifact: artifact, version: version, classifier: classifier, extension: extension) this } diff --git a/src/test/groovy/nebula/test/dependencies/DependencyGraphBuilderSpec.groovy b/src/test/groovy/nebula/test/dependencies/DependencyGraphBuilderSpec.groovy index 42dbf50..fdcf990 100644 --- a/src/test/groovy/nebula/test/dependencies/DependencyGraphBuilderSpec.groovy +++ b/src/test/groovy/nebula/test/dependencies/DependencyGraphBuilderSpec.groovy @@ -16,6 +16,59 @@ class DependencyGraphBuilderSpec extends Specification { foo.group == 'test.nebula' foo.artifact == 'foo' foo.version == '1.0.0' + foo.classifier == null + foo.extension == null + } + + def 'add one dependency with classifier'() { + def builder = new DependencyGraphBuilder() + builder.addModule('test.nebula:foo:1.0.0:bar') + + when: + DependencyGraph graph = builder.build() + + then: + graph.nodes.size() == 1 + Coordinate foo = graph.nodes.find().coordinate + foo.group == 'test.nebula' + foo.artifact == 'foo' + foo.version == '1.0.0' + foo.classifier == 'bar' + foo.extension == null + } + + def 'add one dependency with extension'() { + def builder = new DependencyGraphBuilder() + builder.addModule('test.nebula:foo:1.0.0@zip') + + when: + DependencyGraph graph = builder.build() + + then: + graph.nodes.size() == 1 + Coordinate foo = graph.nodes.find().coordinate + foo.group == 'test.nebula' + foo.artifact == 'foo' + foo.version == '1.0.0' + foo.classifier == null + foo.extension == 'zip' + } + + def 'add one dependency with classifier, extension'() { + def builder = new DependencyGraphBuilder() + builder.addModule('test.nebula:foo:1.0.0:bar@zip') + + when: + DependencyGraph graph = builder.build() + + then: + graph.nodes.size() == 1 + Coordinate foo = graph.nodes.find().coordinate + foo.group == 'test.nebula' + foo.artifact == 'foo' + foo.version == '1.0.0' + foo.classifier == 'bar' + foo.extension == 'zip' } def 'add one dependency with group, artifact, version syntax'() { @@ -31,6 +84,25 @@ class DependencyGraphBuilderSpec extends Specification { foo.group == 'test.nebula' foo.artifact == 'foo' foo.version == '1.0.0' + foo.classifier == null + foo.extension == null + } + + def 'add one dependency with group, artifact, version, classifier, extension syntax'() { + def builder = new DependencyGraphBuilder() + builder.addModule('test.nebula', 'foo', '1.0.0', 'bar', 'zip') + + when: + DependencyGraph graph = builder.build() + + then: + graph.nodes.size() == 1 + Coordinate foo = graph.nodes.find().coordinate + foo.group == 'test.nebula' + foo.artifact == 'foo' + foo.version == '1.0.0' + foo.classifier == 'bar' + foo.extension == 'zip' } def 'add multiple dependencies'() { @@ -47,10 +119,14 @@ class DependencyGraphBuilderSpec extends Specification { foo.group == 'test.nebula' foo.artifact == 'foo' foo.version == '1.0.0' + foo.classifier == null + foo.extension == null Coordinate bar = graph.nodes.find { it.coordinate.artifact == 'bar' }.coordinate bar.group == 'a.nebula' bar.artifact == 'bar' bar.version == '2.0.0' + bar.classifier == null + bar.extension == null } def 'add module with dependencies'() { @@ -81,6 +157,8 @@ class DependencyGraphBuilderSpec extends Specification { dep.group == 'test.nebula' dep.artifact == 'baz' dep.version == '23.1.3' + dep.classifier == null + dep.extension == null } def 'add module with dependencies, verify modules are not replaced with placeholder'() { @@ -100,5 +178,7 @@ class DependencyGraphBuilderSpec extends Specification { dep.group == 'test.nebula' dep.artifact == 'baz' dep.version == '23.1.3' + dep.classifier == null + dep.extension == null } } diff --git a/src/test/groovy/nebula/test/dependencies/DependencyGraphSpec.groovy b/src/test/groovy/nebula/test/dependencies/DependencyGraphSpec.groovy index 4a411c9..53b9929 100644 --- a/src/test/groovy/nebula/test/dependencies/DependencyGraphSpec.groovy +++ b/src/test/groovy/nebula/test/dependencies/DependencyGraphSpec.groovy @@ -28,13 +28,15 @@ class DependencyGraphSpec extends Specification { node.group == 'test' node.artifact == 'foo' node.version == '1.0.0' + node.classifier == null + node.extension == null node.dependencies.size() == 0 node.toString() == 'test:foo:1.0.0' } def 'node with dependencies'() { when: - def graph = new DependencyGraph(['test:foo:1.0.0 -> test:bar:1.+']) + def graph = new DependencyGraph(['test:foo:1.0.0:baz@zip -> test:bar:1.+:bat@jar']) then: graph.nodes.size() == 1 @@ -42,11 +44,15 @@ class DependencyGraphSpec extends Specification { node.group == 'test' node.artifact == 'foo' node.version == '1.0.0' + node.classifier == 'baz' + node.extension == 'zip' node.dependencies.size() == 1 Coordinate dependency = node.dependencies[0] dependency.group == 'test' dependency.artifact == 'bar' - dependency.version == '1.+' + dependency.version == '1.+' + dependency.classifier == 'bat' + dependency.extension == 'jar' } def 'node with multiple dependencies'() { diff --git a/src/test/groovy/nebula/test/dependencies/GradleDependencyGeneratorSpec.groovy b/src/test/groovy/nebula/test/dependencies/GradleDependencyGeneratorSpec.groovy index f27e7e5..2c6362a 100644 --- a/src/test/groovy/nebula/test/dependencies/GradleDependencyGeneratorSpec.groovy +++ b/src/test/groovy/nebula/test/dependencies/GradleDependencyGeneratorSpec.groovy @@ -33,6 +33,45 @@ class GradleDependencyGeneratorSpec extends Specification { new File(mavenRepo, 'test/maven/foo/1.0.0/foo-1.0.0.jar').exists() } + def 'generate a maven repo with a classifier'() { + def directory = 'build/testdependencies/testmavenrepo' + def graph = ['test.maven:foo:1.0.0:bat'] + def generator = new GradleDependencyGenerator(new DependencyGraph(graph), directory) + + when: + generator.generateTestMavenRepo() + + then: + def mavenRepo = new File(directory + '/mavenrepo') + new File(mavenRepo, 'test/maven/foo/1.0.0/foo-1.0.0-bat.jar').exists() + } + + def 'generate a maven repo with a extension'() { + def directory = 'build/testdependencies/testmavenrepo' + def graph = ['test.maven:foo:1.0.0@zip'] + def generator = new GradleDependencyGenerator(new DependencyGraph(graph), directory) + + when: + generator.generateTestMavenRepo() + + then: + def mavenRepo = new File(directory + '/mavenrepo') + new File(mavenRepo, 'test/maven/foo/1.0.0/foo-1.0.0.zip').exists() + } + + def 'generate a maven repo with a classifier and extension'() { + def directory = 'build/testdependencies/testmavenrepo' + def graph = ['test.maven:foo:1.0.0:bar@zip'] + def generator = new GradleDependencyGenerator(new DependencyGraph(graph), directory) + + when: + generator.generateTestMavenRepo() + + then: + def mavenRepo = new File(directory + '/mavenrepo') + new File(mavenRepo, 'test/maven/foo/1.0.0/foo-1.0.0-bar.zip').exists() + } + def 'generate a maven repo with a SNAPSHOT'() { def directory = 'build/testdependencies/testmavenreposnapshot' def graph = ['test.maven:foo:1.0.1-SNAPSHOT'] @@ -62,6 +101,19 @@ class GradleDependencyGeneratorSpec extends Specification { new File(ivyRepo, 'test/ivy/foo/1.0.0/foo-1.0.0.jar').exists() } + def 'generate an ivy repo with classifier and extension'() { + def directory = 'build/testdependencies/testivyrepo' + def graph = ['test.ivy:foo:1.0.0:baz@zip'] + def generator = new GradleDependencyGenerator(new DependencyGraph(graph), directory) + + when: + generator.generateTestIvyRepo() + + then: + def ivyRepo = new File(directory + '/ivyrepo') + new File(ivyRepo, 'test/ivy/foo/1.0.0/foo-1.0.0-baz.zip').exists() + } + def 'check ivy status'() { def directory = 'build/testdependencies/ivyxml' def graph = ['test.ivy:foo:1.0.0'] @@ -103,6 +155,22 @@ class GradleDependencyGeneratorSpec extends Specification { new File(repo, 'ivyrepo/test/ivy/foo/1.0.0/foo-1.0.0-ivy.xml').text.contains '' } + def 'check ivy xml with dependency with classifier and extension'() { + def directory = 'build/testdependencies/ivyxml' + def graph = ['test.ivy:foo:1.0.0 -> test.ivy:bar:1.1.0:baz@zip'] + def generator = new GradleDependencyGenerator(new DependencyGraph(graph), directory) + + when: + generator.generateTestIvyRepo() + + then: + def repo = new File(directory) + new File(repo, 'test.ivy.foo_1_0_0/build.gradle').text.contains 'compile \'test.ivy:bar:1.1.0:baz@zip\'' + def xml = new File(repo, 'ivyrepo/test/ivy/foo/1.0.0/foo-1.0.0-ivy.xml').text + xml.contains '' + xml.contains '' + } + def 'check maven pom'() { def directory = 'build/testdependencies/mavenpom' def graph = ['test.maven:foo:1.0.0 -> test.maven:bar:1.+'] @@ -121,6 +189,26 @@ class GradleDependencyGeneratorSpec extends Specification { pom.contains 'compile' } + def 'check maven pom with dependency with classifier and extension'() { + def directory = 'build/testdependencies/mavenpom' + def graph = ['test.maven:foo:1.0.0 -> test.maven:bar:1.+:baz@zip'] + def generator = new GradleDependencyGenerator(new DependencyGraph(graph), directory) + + when: + generator.generateTestMavenRepo() + + then: + def repo = new File(directory) + new File(repo, 'test.maven.foo_1_0_0/build.gradle').text.contains 'compile \'test.maven:bar:1.+:baz@zip\'' + def pom = new File(repo, 'mavenrepo/test/maven/foo/1.0.0/foo-1.0.0.pom').text + pom.contains 'test.maven' + pom.contains 'bar' + pom.contains '1.+' + pom.contains 'compile' + pom.contains 'baz' + pom.contains 'zip' + } + def 'multiple libraries with dependencies'() { def graph = ['integration.test:foo:1.0.0', 'integration.test:foo:1.0.1', diff --git a/src/test/groovy/nebula/test/dependencies/ModuleBuilderSpec.groovy b/src/test/groovy/nebula/test/dependencies/ModuleBuilderSpec.groovy index 54250b7..0f41508 100644 --- a/src/test/groovy/nebula/test/dependencies/ModuleBuilderSpec.groovy +++ b/src/test/groovy/nebula/test/dependencies/ModuleBuilderSpec.groovy @@ -13,6 +13,54 @@ class ModuleBuilderSpec extends Specification { module.group == 'test.modulebuilder' module.artifact == 'foo' module.version == '1.0.0' + module.classifier == null + module.extension == null + module.dependencies.size() == 0 + } + + def 'build module with classifier with no dependencies'() { + def builder = new ModuleBuilder('test.modulebuilder:foo:1.0.0:bar') + + when: + DependencyGraphNode module = builder.build() + + then: + module.group == 'test.modulebuilder' + module.artifact == 'foo' + module.version == '1.0.0' + module.classifier == 'bar' + module.extension == null + module.dependencies.size() == 0 + } + + + def 'build module with extension with no dependencies'() { + def builder = new ModuleBuilder('test.modulebuilder:foo:1.0.0@zip') + + when: + DependencyGraphNode module = builder.build() + + then: + module.group == 'test.modulebuilder' + module.artifact == 'foo' + module.version == '1.0.0' + module.classifier == null + module.extension == 'zip' + module.dependencies.size() == 0 + } + + def 'build module with classifier and extension with no dependencies'() { + def builder = new ModuleBuilder('test.modulebuilder:foo:1.0.0:bar@zip') + + when: + DependencyGraphNode module = builder.build() + + then: + module.group == 'test.modulebuilder' + module.artifact == 'foo' + module.version == '1.0.0' + module.classifier == 'bar' + module.extension == 'zip' module.dependencies.size() == 0 } @@ -26,6 +74,23 @@ class ModuleBuilderSpec extends Specification { module.group == 'test.modulebuilder' module.artifact == 'foo' module.version == '1.0.0' + module.classifier == null + module.extension == null + module.dependencies.size() == 0 + } + + def 'build module with no dependencies separate group, artifact, version, classifer, extension'() { + def builder = new ModuleBuilder('test.modulebuilder', 'foo', '1.0.0', 'bar', 'zip') + + when: + DependencyGraphNode module = builder.build() + + then: + module.group == 'test.modulebuilder' + module.artifact == 'foo' + module.version == '1.0.0' + module.classifier == 'bar' + module.extension == 'zip' module.dependencies.size() == 0 } @@ -42,12 +107,31 @@ class ModuleBuilderSpec extends Specification { dep.group == 'test.dependency' dep.artifact == 'baz' dep.version == '2.0.1' + dep.classifier == null + dep.extension == null + } + + def 'add dependency with classifier, extension'() { + def builder = new ModuleBuilder('test.modulebuilder', 'bar', '1.0.0') + builder.addDependency('test.dependency', 'baz', '2.0.1', 'bar', 'zip') + + when: + DependencyGraphNode module = builder.build() + + then: + module.dependencies.size() == 1 + def dep = module.dependencies.find() + dep.group == 'test.dependency' + dep.artifact == 'baz' + dep.version == '2.0.1' + dep.classifier == 'bar' + dep.extension == 'zip' } def 'add dependencies'() { def builder = new ModuleBuilder('test.modulebuilder', 'bar', '1.0.0') builder.addDependency('test.dependency', 'baz', '2.0.1') - .addDependency('test.dependency:qux:42.13.0') + .addDependency('test.dependency:qux:42.13.0:bar@zip') when: DependencyGraphNode module = builder.build() @@ -58,9 +142,13 @@ class ModuleBuilderSpec extends Specification { baz.group == 'test.dependency' baz.artifact == 'baz' baz.version == '2.0.1' + baz.classifier == null + baz.extension == null def qux = module.dependencies.find { it.artifact == 'qux' } qux.group == 'test.dependency' qux.artifact == 'qux' qux.version == '42.13.0' + qux.classifier == 'bar' + qux.extension == 'zip' } }