Merge pull request #1406 from mhalbritter

* pr/1406:
  Polish "Make optional/developmentOnly more generic"
  Make optional/developmentOnly more generic

Closes gh-1406
This commit is contained in:
Stephane Nicoll
2023-05-24 13:13:04 +02:00
8 changed files with 292 additions and 70 deletions

View File

@@ -0,0 +1,52 @@
/*
* Copyright 2012-2023 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
*
* https://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.generator.spring.build.gradle;
import io.spring.initializr.generator.buildsystem.Dependency;
import io.spring.initializr.generator.buildsystem.gradle.GradleBuild;
import io.spring.initializr.generator.buildsystem.gradle.GradleDependency;
import io.spring.initializr.generator.spring.build.BuildCustomizer;
/**
* Gradle {@link BuildCustomizer} that sets the "developmentOnly" configuration for a
* dependency.
*
* @author Stephane Nicoll
* @author Moritz Halbritter
*/
public class DevelopmentOnlyDependencyGradleBuildCustomizer implements BuildCustomizer<GradleBuild> {
private final String dependencyId;
/**
* Create a new instance with the identifier for the dependency.
* @param dependencyId the id of the dependency
*/
public DevelopmentOnlyDependencyGradleBuildCustomizer(String dependencyId) {
this.dependencyId = dependencyId;
}
@Override
public void customize(GradleBuild build) {
Dependency dependency = build.dependencies().get(this.dependencyId);
if (dependency != null) {
build.dependencies()
.add(this.dependencyId, GradleDependency.from(dependency).configuration("developmentOnly"));
}
}
}

View File

@@ -0,0 +1,50 @@
/*
* Copyright 2012-2023 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
*
* https://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.generator.spring.build.maven;
import io.spring.initializr.generator.buildsystem.Dependency;
import io.spring.initializr.generator.buildsystem.maven.MavenBuild;
import io.spring.initializr.generator.buildsystem.maven.MavenDependency;
import io.spring.initializr.generator.spring.build.BuildCustomizer;
/**
* Maven {@link BuildCustomizer} that sets the "optional" flag for a dependency.
*
* @author Stephane Nicoll
* @author Moritz Halbritter
*/
public class OptionalDependencyMavenBuildCustomizer implements BuildCustomizer<MavenBuild> {
private final String dependencyId;
/**
* Create a new instance with the identifier for the dependency.
* @param dependencyId the id of the dependency
*/
public OptionalDependencyMavenBuildCustomizer(String dependencyId) {
this.dependencyId = dependencyId;
}
@Override
public void customize(MavenBuild build) {
Dependency dependency = build.dependencies().get(this.dependencyId);
if (dependency != null) {
build.dependencies().add(this.dependencyId, MavenDependency.from(dependency).optional(true));
}
}
}

View File

@@ -16,27 +16,19 @@
package io.spring.initializr.generator.spring.dependency.devtools; package io.spring.initializr.generator.spring.dependency.devtools;
import io.spring.initializr.generator.buildsystem.Dependency;
import io.spring.initializr.generator.buildsystem.gradle.GradleBuild;
import io.spring.initializr.generator.buildsystem.gradle.GradleDependency;
import io.spring.initializr.generator.spring.build.BuildCustomizer; import io.spring.initializr.generator.spring.build.BuildCustomizer;
import io.spring.initializr.generator.spring.build.gradle.DevelopmentOnlyDependencyGradleBuildCustomizer;
import io.spring.initializr.generator.version.Version; import io.spring.initializr.generator.version.Version;
import io.spring.initializr.generator.version.VersionParser;
import io.spring.initializr.generator.version.VersionRange;
/** /**
* Gradle {@link BuildCustomizer} that creates a dedicated "developmentOnly" configuration * Gradle {@link BuildCustomizer} that creates a dedicated "developmentOnly" configuration
* when devtools is selected. * when devtools is selected.
* *
* @author Stephane Nicoll * @author Stephane Nicoll
* @deprecated in favor of {@link DevelopmentOnlyDependencyGradleBuildCustomizer}
*/ */
public class DevToolsGradleBuildCustomizer implements BuildCustomizer<GradleBuild> { @Deprecated(since = "0.20.0", forRemoval = true)
public class DevToolsGradleBuildCustomizer extends DevelopmentOnlyDependencyGradleBuildCustomizer {
private static final VersionRange SPRING_BOOT_2_3_0_RC1_OR_LATER = VersionParser.DEFAULT.parseRange("2.3.0.RC1");
private final Version platformVersion;
private final String devtoolsDependencyId;
/** /**
* Create a new instance with the requested {@link Version platform version} and the * Create a new instance with the requested {@link Version platform version} and the
@@ -45,23 +37,7 @@ public class DevToolsGradleBuildCustomizer implements BuildCustomizer<GradleBuil
* @param devtoolsDependencyId the id of the devtools dependency * @param devtoolsDependencyId the id of the devtools dependency
*/ */
public DevToolsGradleBuildCustomizer(Version platformVersion, String devtoolsDependencyId) { public DevToolsGradleBuildCustomizer(Version platformVersion, String devtoolsDependencyId) {
this.platformVersion = platformVersion; super(devtoolsDependencyId);
this.devtoolsDependencyId = devtoolsDependencyId;
}
@Override
public void customize(GradleBuild build) {
Dependency devtools = build.dependencies().get(this.devtoolsDependencyId);
if (devtools == null) {
return;
}
if (!SPRING_BOOT_2_3_0_RC1_OR_LATER.match(this.platformVersion)) {
build.configurations().add("developmentOnly");
build.configurations()
.customize("runtimeClasspath", (runtimeClasspath) -> runtimeClasspath.extendsFrom("developmentOnly"));
}
build.dependencies()
.add(this.devtoolsDependencyId, GradleDependency.from(devtools).configuration("developmentOnly"));
} }
} }

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright 2012-2019 the original author or authors. * Copyright 2012-2023 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -16,34 +16,24 @@
package io.spring.initializr.generator.spring.dependency.devtools; package io.spring.initializr.generator.spring.dependency.devtools;
import io.spring.initializr.generator.buildsystem.Dependency;
import io.spring.initializr.generator.buildsystem.maven.MavenBuild;
import io.spring.initializr.generator.buildsystem.maven.MavenDependency;
import io.spring.initializr.generator.spring.build.BuildCustomizer; import io.spring.initializr.generator.spring.build.BuildCustomizer;
import io.spring.initializr.generator.spring.build.maven.OptionalDependencyMavenBuildCustomizer;
/** /**
* Maven {@link BuildCustomizer} that sets the "optional" flag when devtools is selected. * Maven {@link BuildCustomizer} that sets the "optional" flag when devtools is selected.
* *
* @author Stephane Nicoll * @author Stephane Nicoll
* @deprecated in favor of {@link OptionalDependencyMavenBuildCustomizer}
*/ */
public class DevToolsMavenBuildCustomizer implements BuildCustomizer<MavenBuild> { @Deprecated(since = "0.20.0", forRemoval = true)
public class DevToolsMavenBuildCustomizer extends OptionalDependencyMavenBuildCustomizer {
private final String devtoolsDependencyId;
/** /**
* Create a new instance with the identifier for the devtools dependency. * Create a new instance with the identifier for the devtools dependency.
* @param devtoolsDependencyId the id of the devtools dependency * @param devtoolsDependencyId the id of the devtools dependency
*/ */
public DevToolsMavenBuildCustomizer(String devtoolsDependencyId) { public DevToolsMavenBuildCustomizer(String devtoolsDependencyId) {
this.devtoolsDependencyId = devtoolsDependencyId; super(devtoolsDependencyId);
}
@Override
public void customize(MavenBuild build) {
Dependency devtools = build.dependencies().get(this.devtoolsDependencyId);
if (devtools != null) {
build.dependencies().add("devtools", MavenDependency.from(devtools).optional(true));
}
} }
} }

View File

@@ -0,0 +1,85 @@
/*
* Copyright 2012-2023 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
*
* https://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.generator.spring.build.gradle;
import io.spring.initializr.generator.buildsystem.Dependency;
import io.spring.initializr.generator.buildsystem.gradle.GradleBuild;
import io.spring.initializr.generator.buildsystem.gradle.GradleDependency;
import org.junit.jupiter.api.Test;
import static org.assertj.core.api.Assertions.assertThat;
/**
* Tests for {@link DevelopmentOnlyDependencyGradleBuildCustomizer}.
*
* @author Stephane Nicoll
* @author Moritz Halbritter
*/
class DevelopmentOnlyDependencyGradleBuildCustomizerTests {
private static final Dependency WEB_DEPENDENCY = Dependency
.withCoordinates("org.springframework.boot", "spring-boot-starter-web")
.build();
private static final Dependency DEVTOOLS_DEPENDENCY = Dependency
.withCoordinates("org.springframework.boot", "spring-boot-devtools")
.build();
@Test
void shouldAddDevelopmentOnlyConfiguration() {
GradleBuild build = new GradleBuild();
build.dependencies().add("devtools", DEVTOOLS_DEPENDENCY);
new DevelopmentOnlyDependencyGradleBuildCustomizer("devtools").customize(build);
Dependency devtools = build.dependencies().get("devtools");
assertThat(devtools).isInstanceOf(GradleDependency.class);
assertThat(((GradleDependency) devtools).getConfiguration()).isEqualTo("developmentOnly");
}
@Test
void shouldNotFailOnDuplicateDependencies() {
GradleBuild build = new GradleBuild();
build.dependencies().add("devtools", DEVTOOLS_DEPENDENCY);
build.dependencies().add("devtools", DEVTOOLS_DEPENDENCY);
build.dependencies().add("web", WEB_DEPENDENCY);
new DevelopmentOnlyDependencyGradleBuildCustomizer("devtools").customize(build);
Dependency devtools = build.dependencies().get("devtools");
assertThat(devtools).isInstanceOf(GradleDependency.class);
assertThat(((GradleDependency) devtools).getConfiguration()).isEqualTo("developmentOnly");
}
@Test
void shouldIgnoreOtherDependencies() {
GradleBuild build = new GradleBuild();
build.dependencies().add("devtools", DEVTOOLS_DEPENDENCY);
build.dependencies().add("web", WEB_DEPENDENCY);
new DevelopmentOnlyDependencyGradleBuildCustomizer("devtools").customize(build);
Dependency devtools = build.dependencies().get("devtools");
assertThat(devtools).isInstanceOf(GradleDependency.class);
assertThat(((GradleDependency) devtools).getConfiguration()).isEqualTo("developmentOnly");
Dependency web = build.dependencies().get("web");
assertThat(web).isNotInstanceOf(GradleDependency.class);
}
@Test
void shouldNotChangeDependencies() {
GradleBuild build = new GradleBuild();
build.dependencies().add("web", WEB_DEPENDENCY);
new DevelopmentOnlyDependencyGradleBuildCustomizer("devtools").customize(build);
assertThat(build.dependencies().ids()).containsOnly("web");
}
}

View File

@@ -0,0 +1,84 @@
/*
* Copyright 2012-2023 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
*
* https://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.generator.spring.build.maven;
import io.spring.initializr.generator.buildsystem.Dependency;
import io.spring.initializr.generator.buildsystem.maven.MavenBuild;
import io.spring.initializr.generator.buildsystem.maven.MavenDependency;
import org.junit.jupiter.api.Test;
import static org.assertj.core.api.Assertions.assertThat;
/**
* Tests for {@link OptionalDependencyMavenBuildCustomizer}.
*
* @author Stephane Nicoll
* @author Moritz Halbritter
*/
class OptionalDependencyMavenBuildCustomizerTests {
private static final Dependency WEB_DEPENDENCY = Dependency
.withCoordinates("org.springframework.boot", "spring-boot-starter-web")
.build();
private static final Dependency DEVTOOLS_DEPENDENCY = Dependency
.withCoordinates("org.springframework.boot", "spring-boot-devtools")
.build();
@Test
void shouldAddOptionalScope() {
MavenBuild build = new MavenBuild();
build.dependencies().add("devtools", DEVTOOLS_DEPENDENCY);
new OptionalDependencyMavenBuildCustomizer("devtools").customize(build);
Dependency devtools = build.dependencies().get("devtools");
assertThat(devtools).isInstanceOf(MavenDependency.class);
assertThat(((MavenDependency) devtools).isOptional()).isTrue();
}
@Test
void shouldNotFailOnDuplicateDependencies() {
MavenBuild build = new MavenBuild();
build.dependencies().add("devtools", DEVTOOLS_DEPENDENCY);
build.dependencies().add("devtools", DEVTOOLS_DEPENDENCY);
new OptionalDependencyMavenBuildCustomizer("devtools").customize(build);
Dependency devtools = build.dependencies().get("devtools");
assertThat(devtools).isInstanceOf(MavenDependency.class);
assertThat(((MavenDependency) devtools).isOptional()).isTrue();
}
@Test
void shouldIgnoreOtherDependencies() {
MavenBuild build = new MavenBuild();
build.dependencies().add("devtools", DEVTOOLS_DEPENDENCY);
build.dependencies().add("web", WEB_DEPENDENCY);
new OptionalDependencyMavenBuildCustomizer("devtools").customize(build);
Dependency devtools = build.dependencies().get("devtools");
assertThat(devtools).isInstanceOf(MavenDependency.class);
assertThat(((MavenDependency) devtools).isOptional()).isTrue();
Dependency web = build.dependencies().get("web");
assertThat(web).isNotInstanceOf(MavenDependency.class);
}
@Test
void shouldNotChangeDependencies() {
MavenBuild build = new MavenBuild();
build.dependencies().add("web", WEB_DEPENDENCY);
new OptionalDependencyMavenBuildCustomizer("devtools").customize(build);
assertThat(build.dependencies().ids()).containsOnly("web");
}
}

View File

@@ -23,13 +23,14 @@ import io.spring.initializr.generator.version.Version;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.mock;
/** /**
* Tests for {@link DevToolsGradleBuildCustomizer}. * Tests for {@link DevToolsGradleBuildCustomizer}.
* *
* @author Stephane Nicoll * @author Stephane Nicoll
*/ */
@Deprecated
@SuppressWarnings("removal")
class DevToolsGradleBuildCustomizerTests { class DevToolsGradleBuildCustomizerTests {
private static final Dependency DEVTOOLS_DEPENDENCY = Dependency private static final Dependency DEVTOOLS_DEPENDENCY = Dependency
@@ -37,39 +38,21 @@ class DevToolsGradleBuildCustomizerTests {
.build(); .build();
@Test @Test
void gradleWithDevtoolsAndSpringBootPriorTo23RC1CreatesDevelopmentOnlyConfiguration() { void gradleWithDevtoolsFlagDependencyAsDevelopmentOnly() {
GradleBuild build = new GradleBuild(); GradleBuild build = new GradleBuild();
build.dependencies().add("devtools", DEVTOOLS_DEPENDENCY); build.dependencies().add("devtools", DEVTOOLS_DEPENDENCY);
new DevToolsGradleBuildCustomizer(Version.parse("2.3.0.M4"), "devtools").customize(build); new DevToolsGradleBuildCustomizer(Version.parse("3.0.0"), "devtools").customize(build);
assertThat(build.configurations().names()).containsOnly("developmentOnly");
assertThat(build.configurations().customizations()).singleElement().satisfies((configuration) -> {
assertThat(configuration.getName()).isEqualTo("runtimeClasspath");
assertThat(configuration.getExtendsFrom()).containsOnly("developmentOnly");
});
Dependency devtools = build.dependencies().get("devtools"); Dependency devtools = build.dependencies().get("devtools");
assertThat(devtools).isInstanceOf(GradleDependency.class); assertThat(devtools).isInstanceOf(GradleDependency.class);
assertThat(((GradleDependency) devtools).getConfiguration()).isEqualTo("developmentOnly"); assertThat(((GradleDependency) devtools).getConfiguration()).isEqualTo("developmentOnly");
} }
@Test @Test
void gradleWithDevtoolsAndSpringBoot23RC1OrLaterDoesNotCreateDevelopmentOnlyConfiguration() { void gradleWithoutDevtoolsDoesNotModifyDependencies() {
GradleBuild build = new GradleBuild(); GradleBuild build = new GradleBuild();
build.dependencies().add("devtools", DEVTOOLS_DEPENDENCY); build.dependencies().add("ignored", DEVTOOLS_DEPENDENCY);
build.dependencies().add("devtools", DEVTOOLS_DEPENDENCY); new DevToolsGradleBuildCustomizer(Version.parse("3.0.0"), "devtools").customize(build);
new DevToolsGradleBuildCustomizer(Version.parse("2.3.0.RC1"), "devtools").customize(build); assertThat(build.dependencies().get("devtools")).isNull();
assertThat(build.configurations().names()).isEmpty();
Dependency devtools = build.dependencies().get("devtools");
assertThat(devtools).isInstanceOf(GradleDependency.class);
assertThat(((GradleDependency) devtools).getConfiguration()).isEqualTo("developmentOnly");
}
@Test
void gradleWithoutDevtoolsAndSpringBootPriorTo23RC1DoesNotCreateDevelopmentOnlyConfiguration() {
GradleBuild build = new GradleBuild();
build.dependencies().add("web", mock(Dependency.class));
new DevToolsGradleBuildCustomizer(Version.parse("2.3.0.M4"), "devtools").customize(build);
assertThat(build.configurations().names()).isEmpty();
assertThat(build.dependencies().ids()).containsOnly("web");
} }
} }

View File

@@ -29,6 +29,8 @@ import static org.mockito.Mockito.mock;
* *
* @author Stephane Nicoll * @author Stephane Nicoll
*/ */
@Deprecated
@SuppressWarnings("removal")
class DevToolsMavenBuildCustomizerTests { class DevToolsMavenBuildCustomizerTests {
private static final Dependency DEVTOOLS_DEPENDENCY = Dependency private static final Dependency DEVTOOLS_DEPENDENCY = Dependency