mirror of
https://gitee.com/dcren/initializr.git
synced 2025-09-18 17:48:14 +08:00
Support for custom repository
A dependency or a dependency group may now declare a repository in case it is not available in Maven central Closes gh-125
This commit is contained in:
@@ -20,6 +20,7 @@ import groovy.util.logging.Slf4j
|
||||
import io.spring.initializr.metadata.BillOfMaterials
|
||||
import io.spring.initializr.metadata.Dependency
|
||||
import io.spring.initializr.metadata.InitializrMetadata
|
||||
import io.spring.initializr.metadata.Repository
|
||||
import io.spring.initializr.metadata.Type
|
||||
import io.spring.initializr.util.Version
|
||||
import io.spring.initializr.util.VersionRange
|
||||
@@ -62,6 +63,8 @@ class ProjectRequest {
|
||||
|
||||
final List<BillOfMaterials> boms = []
|
||||
|
||||
final Map<String, Repository> repositories = [:]
|
||||
|
||||
def facets = []
|
||||
def build
|
||||
|
||||
@@ -116,6 +119,12 @@ class ProjectRequest {
|
||||
boms << metadata.configuration.env.boms[bomId]
|
||||
}
|
||||
}
|
||||
if (it.repository) {
|
||||
String repositoryId = it.repository
|
||||
if (!repositories[repositoryId]) {
|
||||
repositories[repositoryId] = metadata.configuration.env.repositories[repositoryId]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (this.type) {
|
||||
@@ -133,6 +142,11 @@ class ProjectRequest {
|
||||
this.applicationName = metadata.configuration.generateApplicationName(this.name)
|
||||
}
|
||||
|
||||
if (!'RELEASE'.equals(requestedVersion.qualifier.qualifier)) {
|
||||
repositories['spring-snapshots'] = metadata.configuration.env.repositories['spring-snapshots']
|
||||
repositories['spring-milestones'] = metadata.configuration.env.repositories['spring-milestones']
|
||||
}
|
||||
|
||||
afterResolution(metadata)
|
||||
}
|
||||
|
||||
|
@@ -74,6 +74,9 @@ class DependenciesCapability extends ServiceCapability<List<DependencyGroup>> {
|
||||
if (!dependency.bom && group.bom) {
|
||||
dependency.bom = group.bom
|
||||
}
|
||||
if (!dependency.repository && group.repository) {
|
||||
dependency.repository = group.repository
|
||||
}
|
||||
|
||||
dependency.resolve()
|
||||
indexDependency(dependency.id, dependency)
|
||||
|
@@ -61,6 +61,8 @@ class Dependency extends MetadataElement {
|
||||
|
||||
String bom
|
||||
|
||||
String repository
|
||||
|
||||
void setScope(String scope) {
|
||||
if (!SCOPE_ALL.contains(scope)) {
|
||||
throw new InvalidInitializrMetadataException("Invalid scope $scope must be one of $SCOPE_ALL")
|
||||
|
@@ -45,6 +45,13 @@ class DependencyGroup {
|
||||
@JsonIgnore
|
||||
String bom
|
||||
|
||||
/**
|
||||
* The default repository to associate to all dependencies of this group unless
|
||||
* specified otherwise.
|
||||
*/
|
||||
@JsonIgnore
|
||||
String repository
|
||||
|
||||
final List<Dependency> content = []
|
||||
|
||||
}
|
||||
|
@@ -15,6 +15,7 @@
|
||||
*/
|
||||
|
||||
package io.spring.initializr.metadata
|
||||
|
||||
/**
|
||||
* Various configuration options used by the service.
|
||||
*
|
||||
@@ -117,6 +118,18 @@ class InitializrConfiguration {
|
||||
*/
|
||||
final Map<String, BillOfMaterials> boms = [:]
|
||||
|
||||
/**
|
||||
* The {@link Repository} instances that are referenced in this instance.
|
||||
*/
|
||||
final Map<String, Repository> repositories = [:]
|
||||
|
||||
Env() {
|
||||
repositories['spring-snapshots'] = new Repository(name: 'Spring Snapshots',
|
||||
url: new URL('https://repo.spring.io/snapshot'), snapshotsEnabled: true)
|
||||
repositories['spring-milestones'] = new Repository(name: 'Spring Milestones',
|
||||
url: new URL('https://repo.spring.io/milestone'), snapshotsEnabled: false)
|
||||
}
|
||||
|
||||
void setArtifactRepository(String artifactRepository) {
|
||||
if (!artifactRepository.endsWith('/')) {
|
||||
artifactRepository = artifactRepository + '/'
|
||||
@@ -135,6 +148,11 @@ class InitializrConfiguration {
|
||||
boms[id] = bom
|
||||
}
|
||||
}
|
||||
other.repositories.each { id, repo ->
|
||||
if (!repositories[id]) {
|
||||
repositories[id] = repo
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -94,6 +94,11 @@ class InitializrMetadata {
|
||||
throw new InvalidInitializrMetadataException("Dependency $dependency " +
|
||||
"defines an invalid BOM id $dependency.bom, available boms $boms")
|
||||
}
|
||||
def repositories = configuration.env.repositories
|
||||
if (dependency.repository && !repositories[dependency.repository]) {
|
||||
throw new InvalidInitializrMetadataException("Dependency $dependency " +
|
||||
"defines an invalid repository id $dependency.repository, available repositores $repositories")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Copyright 2012-2015 the original author or 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.spring.initializr.metadata
|
||||
|
||||
/**
|
||||
* Define a repository to be represented in the generated project
|
||||
* if a dependency refers to it.
|
||||
*
|
||||
* @author Stephane Nicoll
|
||||
* @since 1.0
|
||||
*/
|
||||
class Repository {
|
||||
|
||||
String name
|
||||
URL url
|
||||
boolean snapshotsEnabled
|
||||
|
||||
}
|
@@ -30,9 +30,8 @@ sourceCompatibility = ${javaVersion}
|
||||
targetCompatibility = ${javaVersion}
|
||||
|
||||
repositories {
|
||||
mavenCentral()<% if (!bootVersion.contains("RELEASE")) { %>
|
||||
maven { url "https://repo.spring.io/snapshot" }
|
||||
maven { url "https://repo.spring.io/milestone" }<% } %>
|
||||
mavenCentral()<% if (repositories) { repositories.each { key, repo -> %>
|
||||
maven { url "${repo.url}" }<% }} %>
|
||||
}
|
||||
|
||||
<% if (packaging=='war') { %>configurations {
|
||||
|
@@ -107,26 +107,18 @@
|
||||
<extensions>true</extensions>
|
||||
</plugin><% } %>
|
||||
</plugins>
|
||||
</build><% if (!bootVersion.contains("RELEASE")) { %>
|
||||
|
||||
<repositories>
|
||||
</build>
|
||||
<% if (repositories) { %>
|
||||
<repositories><% repositories.each { key, repo -> %>
|
||||
<repository>
|
||||
<id>spring-snapshots</id>
|
||||
<name>Spring Snapshots</name>
|
||||
<url>https://repo.spring.io/snapshot</url>
|
||||
<id>${key}</id>
|
||||
<name>${repo.name}</name>
|
||||
<url>${repo.url}</url>
|
||||
<snapshots>
|
||||
<enabled>true</enabled>
|
||||
<enabled>${repo.snapshotsEnabled}</enabled>
|
||||
</snapshots>
|
||||
</repository>
|
||||
<repository>
|
||||
<id>spring-milestones</id>
|
||||
<name>Spring Milestones</name>
|
||||
<url>https://repo.spring.io/milestone</url>
|
||||
<snapshots>
|
||||
<enabled>false</enabled>
|
||||
</snapshots>
|
||||
</repository>
|
||||
</repositories>
|
||||
</repository><% } %>
|
||||
</repositories><% } %><% if (!bootVersion.contains("RELEASE")) { %>
|
||||
<pluginRepositories>
|
||||
<pluginRepository>
|
||||
<id>spring-snapshots</id>
|
||||
@@ -144,7 +136,6 @@
|
||||
<enabled>false</enabled>
|
||||
</snapshots>
|
||||
</pluginRepository>
|
||||
</pluginRepositories>
|
||||
<% } %>
|
||||
</pluginRepositories><% } %>
|
||||
|
||||
</project>
|
||||
|
@@ -247,6 +247,13 @@ class ProjectGeneratorTests {
|
||||
.hasSpringBootStarterDependency('web')
|
||||
}
|
||||
|
||||
@Test
|
||||
void gradleBuildWithBootSnapshot() {
|
||||
def request = createProjectRequest('web')
|
||||
request.bootVersion = '1.0.1.BUILD-SNAPSHOT'
|
||||
generateGradleBuild(request).hasSnapshotRepository()
|
||||
}
|
||||
|
||||
@Test
|
||||
void gradleBuildWithCustomVersion() {
|
||||
def whatever = new Dependency(id: 'whatever', groupId: 'org.acme', artifactId: 'whatever', version: '1.2.3')
|
||||
@@ -364,6 +371,44 @@ class ProjectGeneratorTests {
|
||||
.contains("mavenBom \"org.acme:foo-bom:1.2.3\"")
|
||||
}
|
||||
|
||||
@Test
|
||||
void mavenRepository() {
|
||||
def foo = new Dependency(id: 'foo', groupId: 'org.acme', artifactId: 'foo', repository: 'foo-repo')
|
||||
def metadata = InitializrMetadataTestBuilder.withDefaults()
|
||||
.addDependencyGroup('foo', foo)
|
||||
.addRepository('foo-repo', 'foo', 'http://example.com/repo', false).build()
|
||||
projectGenerator.metadata = metadata
|
||||
def request = createProjectRequest('foo')
|
||||
generateMavenPom(request).hasDependency(foo)
|
||||
.hasRepository('foo-repo', 'foo', 'http://example.com/repo', false)
|
||||
}
|
||||
|
||||
@Test
|
||||
void mavenRepositoryWithSeveralDependenciesOnSameRepository() {
|
||||
def foo = new Dependency(id: 'foo', groupId: 'org.acme', artifactId: 'foo', repository: 'the-repo')
|
||||
def bar = new Dependency(id: 'bar', groupId: 'org.acme', artifactId: 'bar', repository: 'the-repo')
|
||||
def metadata = InitializrMetadataTestBuilder.withDefaults()
|
||||
.addDependencyGroup('group', foo, bar)
|
||||
.addRepository('the-repo', 'repo', 'http://example.com/repo', true).build()
|
||||
projectGenerator.metadata = metadata
|
||||
def request = createProjectRequest('foo', 'bar')
|
||||
generateMavenPom(request).hasDependency(foo)
|
||||
.hasRepository('the-repo', 'repo', 'http://example.com/repo', true)
|
||||
.hasRepositoriesCount(1)
|
||||
}
|
||||
|
||||
@Test
|
||||
void gradleRepository() {
|
||||
def foo = new Dependency(id: 'foo', groupId: 'org.acme', artifactId: 'foo', repository: 'foo-repo')
|
||||
def metadata = InitializrMetadataTestBuilder.withDefaults()
|
||||
.addDependencyGroup('foo', foo)
|
||||
.addRepository('foo-repo', 'foo', 'http://example.com/repo', false).build()
|
||||
projectGenerator.metadata = metadata
|
||||
def request = createProjectRequest('foo')
|
||||
generateGradleBuild(request)
|
||||
.hasRepository('http://example.com/repo')
|
||||
}
|
||||
|
||||
PomAssert generateMavenPom(ProjectRequest request) {
|
||||
def content = new String(projectGenerator.generateMavenPom(request))
|
||||
new PomAssert(content).validateProjectRequest(request)
|
||||
|
@@ -131,6 +131,21 @@ class DependenciesCapabilityTest {
|
||||
assertEquals 'da-bom', capability.get('second').bom
|
||||
}
|
||||
|
||||
@Test
|
||||
void addDefaultRepository() {
|
||||
def first = new Dependency(id: 'first')
|
||||
def second = new Dependency(id: 'second', repository: 'da-repo')
|
||||
def group = createDependencyGroup('test', first, second)
|
||||
group.repository = 'test-repo'
|
||||
|
||||
DependenciesCapability capability = new DependenciesCapability()
|
||||
capability.content << group
|
||||
capability.validate()
|
||||
|
||||
assertEquals 'test-repo', capability.get('first').repository
|
||||
assertEquals 'da-repo', capability.get('second').repository
|
||||
}
|
||||
|
||||
|
||||
private static DependenciesCapability createDependenciesCapability(String groupName, Dependency... dependencies) {
|
||||
DependenciesCapability capability = new DependenciesCapability()
|
||||
|
@@ -105,6 +105,26 @@ class InitializrMetadataBuilderTests {
|
||||
assertEquals '4.5.6.RELEASE', anotherBom.version
|
||||
}
|
||||
|
||||
@Test
|
||||
void mergeMetadataWithRepository() {
|
||||
def metadata = InitializrMetadataBuilder.create().withInitializrMetadata(
|
||||
new ClassPathResource('metadata/config/test-repository.json')).build()
|
||||
|
||||
def repositories = metadata.configuration.env.repositories
|
||||
assertEquals 4, repositories.size() // 2 standard repos
|
||||
Repository myRepo = repositories['my-repo']
|
||||
assertNotNull myRepo
|
||||
assertEquals 'my repo', myRepo.name
|
||||
assertEquals new URL('http://example.com/my'), myRepo.url
|
||||
assertEquals true, myRepo.snapshotsEnabled
|
||||
|
||||
Repository anotherRepo = repositories['another-repo']
|
||||
assertNotNull anotherRepo
|
||||
assertEquals 'another repo', anotherRepo.name
|
||||
assertEquals new URL('http://example.com/another'), anotherRepo.url
|
||||
assertEquals false, anotherRepo.snapshotsEnabled
|
||||
}
|
||||
|
||||
@Test
|
||||
void mergeConfigurationDisabledByDefault() {
|
||||
def config = load(new ClassPathResource("application-test-default.yml"))
|
||||
|
@@ -42,4 +42,17 @@ class InitializrMetadataTests {
|
||||
builder.build()
|
||||
}
|
||||
|
||||
@Test
|
||||
void invalidRepository() {
|
||||
def foo = new Dependency(id: 'foo', groupId: 'org.acme', artifactId: 'foo', repository: 'foo-repo')
|
||||
InitializrMetadataTestBuilder builder = InitializrMetadataTestBuilder
|
||||
.withDefaults().addRepository('my-repo', 'repo', 'http://example.com/repo', true)
|
||||
.addDependencyGroup('test', foo);
|
||||
|
||||
thrown.expect(InvalidInitializrMetadataException)
|
||||
thrown.expectMessage("foo-repo")
|
||||
thrown.expectMessage("my-repo")
|
||||
builder.build()
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -60,6 +60,14 @@ class GradleBuildAssert {
|
||||
contains("targetCompatibility = $javaVersion")
|
||||
}
|
||||
|
||||
GradleBuildAssert hasSnapshotRepository() {
|
||||
contains('https://repo.spring.io/snapshot')
|
||||
}
|
||||
|
||||
GradleBuildAssert hasRepository(String url) {
|
||||
contains("maven { url \"$url\" }")
|
||||
}
|
||||
|
||||
GradleBuildAssert contains(String expression) {
|
||||
assertTrue "$expression has not been found in gradle build $content", content.contains(expression)
|
||||
this
|
||||
|
@@ -22,6 +22,7 @@ import io.spring.initializr.metadata.Dependency
|
||||
import io.spring.initializr.metadata.DependencyGroup
|
||||
import io.spring.initializr.metadata.InitializrMetadata
|
||||
import io.spring.initializr.metadata.InitializrMetadataBuilder
|
||||
import io.spring.initializr.metadata.Repository
|
||||
import io.spring.initializr.metadata.Type
|
||||
|
||||
/**
|
||||
@@ -149,4 +150,13 @@ class InitializrMetadataTestBuilder {
|
||||
this
|
||||
}
|
||||
|
||||
InitializrMetadataTestBuilder addRepository(String id, String name, String url, boolean snapshotsEnabled) {
|
||||
builder.withCustomizer {
|
||||
Repository repo = new Repository(
|
||||
name: name, url: new URL(url), snapshotsEnabled: snapshotsEnabled)
|
||||
it.configuration.env.repositories[id] = repo
|
||||
}
|
||||
this
|
||||
}
|
||||
|
||||
}
|
@@ -19,6 +19,7 @@ package io.spring.initializr.test
|
||||
import io.spring.initializr.generator.ProjectRequest
|
||||
import io.spring.initializr.metadata.BillOfMaterials
|
||||
import io.spring.initializr.metadata.Dependency
|
||||
import io.spring.initializr.metadata.Repository
|
||||
import org.custommonkey.xmlunit.SimpleNamespaceContext
|
||||
import org.custommonkey.xmlunit.XMLUnit
|
||||
import org.custommonkey.xmlunit.XpathEngine
|
||||
@@ -41,6 +42,7 @@ class PomAssert {
|
||||
final Document doc
|
||||
final Map<String, Dependency> dependencies = [:]
|
||||
final Map<String, BillOfMaterials> boms = [:]
|
||||
final Map<String, Repository> repositories = [:]
|
||||
|
||||
PomAssert(String content) {
|
||||
eng = XMLUnit.newXpathEngine()
|
||||
@@ -51,6 +53,7 @@ class PomAssert {
|
||||
doc = XMLUnit.buildControlDocument(content)
|
||||
parseDependencies()
|
||||
parseBoms()
|
||||
parseRepositories()
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -165,21 +168,34 @@ class PomAssert {
|
||||
}
|
||||
|
||||
PomAssert hasSnapshotRepository() {
|
||||
hasRepository('spring-snapshots')
|
||||
hasRepository('spring-snapshots', 'Spring Snapshots',
|
||||
'https://repo.spring.io/snapshot', true)
|
||||
hasPluginRepository('spring-snapshots')
|
||||
this
|
||||
}
|
||||
|
||||
def hasRepository(String name) {
|
||||
def nodes = eng.getMatchingNodes(createRootNodeXPath('repositories/pom:repository/pom:id'), doc)
|
||||
for (int i = 0; i < nodes.length; i++) {
|
||||
if (name.equals(nodes.item(i).textContent)) {
|
||||
return
|
||||
}
|
||||
PomAssert hasRepository(String id, String name, String url, Boolean snapshotsEnabled) {
|
||||
Repository repository = repositories[id]
|
||||
assertNotNull "No repository found with '$id' --> ${repositories.keySet()}", repository
|
||||
if (name) {
|
||||
assertEquals "Wrong name for $repository", name, repository.name
|
||||
}
|
||||
throw new IllegalArgumentException("No repository found with id $name")
|
||||
if (url) {
|
||||
assertEquals "Wrong url for $repository", new URL(url), repository.url
|
||||
}
|
||||
if (snapshotsEnabled) {
|
||||
assertEquals "Wrong snapshots enabled flag for $repository", snapshotsEnabled, repository.snapshotsEnabled
|
||||
}
|
||||
this
|
||||
}
|
||||
|
||||
PomAssert hasRepositoriesCount(int count) {
|
||||
assertEquals "Wrong number of declared repositories -->'${repositories.keySet()}",
|
||||
count, repositories.size()
|
||||
this
|
||||
}
|
||||
|
||||
|
||||
def hasPluginRepository(String name) {
|
||||
def nodes = eng.getMatchingNodes(createRootNodeXPath('pluginRepositories/pom:pluginRepository/pom:id'), doc)
|
||||
for (int i = 0; i < nodes.length; i++) {
|
||||
@@ -258,6 +274,37 @@ class PomAssert {
|
||||
}
|
||||
}
|
||||
|
||||
private def parseRepositories() {
|
||||
def nodes = eng.getMatchingNodes(createRootNodeXPath('repositories/pom:repository'), doc)
|
||||
for (int i = 0; i < nodes.length; i++) {
|
||||
def item = nodes.item(i)
|
||||
if (item instanceof Element) {
|
||||
def repository = new Repository()
|
||||
def element = (Element) item
|
||||
def type = element.getElementsByTagName('id')
|
||||
def id = type.item(0).textContent
|
||||
def name = element.getElementsByTagName('name')
|
||||
if (name.length > 0) {
|
||||
repository.name = name.item(0).textContent
|
||||
}
|
||||
def url = element.getElementsByTagName('url')
|
||||
if (url.length > 0) {
|
||||
repository.url = new URL(url.item(0).textContent)
|
||||
}
|
||||
def snapshots = element.getElementsByTagName('snapshots')
|
||||
if (snapshots.length > 0) {
|
||||
Element snapshotsElement = (Element) snapshots.item(0);
|
||||
def snapshotsEnabled = snapshotsElement.getElementsByTagName('enabled')
|
||||
if (snapshotsEnabled.length > 0) {
|
||||
repository.snapshotsEnabled = snapshotsEnabled.item(0).textContent
|
||||
}
|
||||
}
|
||||
assertFalse("Duplicate Repository with id $id", repositories.containsKey(id))
|
||||
repositories[id] = repository
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean isBom(def type, def scope) {
|
||||
if (type.length == 0 || scope.length == 0) {
|
||||
return false
|
||||
|
@@ -29,19 +29,29 @@
|
||||
"title": "Spring Boot Version",
|
||||
"type": "SINGLE_SELECT"
|
||||
},
|
||||
"configuration": {
|
||||
"env": {
|
||||
"artifactRepository": "https://repo.spring.io/release/",
|
||||
"boms": {},
|
||||
"fallbackApplicationName": "Application",
|
||||
"forceSsl": true,
|
||||
"invalidApplicationNames": [
|
||||
"SpringApplication",
|
||||
"SpringBootApplication"
|
||||
],
|
||||
"springBootMetadataUrl": "https://spring.io/project_metadata/spring-boot"
|
||||
}
|
||||
},
|
||||
"configuration": {"env": {
|
||||
"artifactRepository": "https://repo.spring.io/release/",
|
||||
"boms": {},
|
||||
"fallbackApplicationName": "Application",
|
||||
"forceSsl": true,
|
||||
"invalidApplicationNames": [
|
||||
"SpringApplication",
|
||||
"SpringBootApplication"
|
||||
],
|
||||
"repositories": {
|
||||
"spring-milestones": {
|
||||
"name": "Spring Milestones",
|
||||
"snapshotsEnabled": false,
|
||||
"url": "https://repo.spring.io/milestone"
|
||||
},
|
||||
"spring-snapshots": {
|
||||
"name": "Spring Snapshots",
|
||||
"snapshotsEnabled": true,
|
||||
"url": "https://repo.spring.io/snapshot"
|
||||
}
|
||||
},
|
||||
"springBootMetadataUrl": "https://spring.io/project_metadata/spring-boot"
|
||||
}},
|
||||
"dependencies": {
|
||||
"content": [
|
||||
{
|
||||
|
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"configuration": {
|
||||
"env": {
|
||||
"repositories": {
|
||||
"my-repo": {
|
||||
"name": "my repo",
|
||||
"url": "http://example.com/my",
|
||||
"snapshotsEnabled": true
|
||||
},
|
||||
"another-repo": {
|
||||
"name": "another repo",
|
||||
"url": "http://example.com/another",
|
||||
"snapshotsEnabled": false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user