mirror of
https://gitee.com/dcren/initializr.git
synced 2025-12-26 22:25:51 +08:00
Add baseDir option
Previously the generated archive wasn't self contained and the user had to create a dedicated directory before extracting it in case the archive utility does not handle that use case (MacOS supports that by default). A baseDir request attribute has been added and generate a base directory in the archive when set. It is enabled by default in the web UI and takes the same value as the artifactId. Other clients are unaffected by this change (and shouldn't probably). Note that the legacy HTML form isn't impacted by this change either as older STS versions expect the archive to have a very specific format. curl-based tools can use that new baseDir request parameter to specify that a base directory is required, something like curl https://start.spring.io/starter.tgz -d baseDir=my-project Closes gh-65
This commit is contained in:
@@ -7,6 +7,9 @@ order.
|
||||
|
||||
=== Release 1.0.0 (In progress)
|
||||
|
||||
* https://github.com/spring-io/initializr/issues/65[#64]: project archives generated by the web UI now contain
|
||||
a base directory equals to the `artifactId`. By default, no base directory gets created if the project is
|
||||
generated by another means; use the new `baseDir` to control that behaviour.
|
||||
* https://github.com/spring-io/initializr/issues/46[#46]: projects generated against Spring 1.2+ are using the
|
||||
new `@SpringBootApplication`
|
||||
* https://github.com/spring-io/initializr/issues/64[#64]: Groovy-based projects are now working properly with
|
||||
|
||||
@@ -74,10 +74,12 @@ class ProjectGenerator {
|
||||
File generateProjectStructure(ProjectRequest request) {
|
||||
def model = initializeModel(request)
|
||||
|
||||
def dir = File.createTempFile('tmp', '', new File(tmpdir))
|
||||
addTempFile(dir.name, dir)
|
||||
dir.delete()
|
||||
dir.mkdirs()
|
||||
def rootDir = File.createTempFile('tmp', '', new File(tmpdir))
|
||||
addTempFile(rootDir.name, rootDir)
|
||||
rootDir.delete()
|
||||
rootDir.mkdirs()
|
||||
|
||||
def dir = initializerProjectDir(rootDir, request)
|
||||
|
||||
if ('gradle'.equals(request.build)) {
|
||||
def gradle = new String(doGenerateGradleBuild(model))
|
||||
@@ -119,7 +121,7 @@ class ProjectGenerator {
|
||||
new File(dir, 'src/main/resources/static').mkdirs()
|
||||
}
|
||||
invokeListeners(request)
|
||||
dir
|
||||
rootDir
|
||||
|
||||
}
|
||||
|
||||
@@ -183,6 +185,16 @@ class ProjectGenerator {
|
||||
template 'starter-build.gradle', model
|
||||
}
|
||||
|
||||
private File initializerProjectDir(File rootDir, ProjectRequest request) {
|
||||
if (request.baseDir) {
|
||||
File dir = new File(rootDir, request.baseDir)
|
||||
dir.mkdir()
|
||||
return dir
|
||||
} else {
|
||||
return rootDir
|
||||
}
|
||||
}
|
||||
|
||||
def write(File target, String templateName, def model) {
|
||||
def tmpl = templateName.endsWith('.groovy') ? templateName + '.tmpl' : templateName
|
||||
def body = template tmpl, model
|
||||
|
||||
@@ -53,6 +53,9 @@ class ProjectRequest {
|
||||
String packageName
|
||||
String javaVersion
|
||||
|
||||
// The base directory to create in the archive - no baseDir by default
|
||||
String baseDir
|
||||
|
||||
// Resolved dependencies based on the ids provided by either "style" or "dependencies"
|
||||
List<InitializrMetadata.Dependency> resolvedDependencies
|
||||
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
</div>
|
||||
</div>
|
||||
<form id="form" class="form-horizontal" action="/starter.zip" method="get" role="form">
|
||||
<input id="baseDir" name="baseDir" type="hidden" value="${defaults.artifactId}">
|
||||
<div class="row">
|
||||
<div class="col-sm-6">
|
||||
<h3>Project metadata</h3>
|
||||
@@ -38,7 +39,7 @@
|
||||
<div class="form-group">
|
||||
<label for="artifactId" class="col-md-3 control-label">Artifact</label>
|
||||
<div class="col-md-8">
|
||||
<input id="artifactId" class="form-control" type="text" value="${defaults.artifactId}" name="artifactId">
|
||||
<input id="artifactId" class="form-control" type="text" value="${defaults.artifactId}" name="artifactId" onchange="javascript:updateBaseDir()">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
@@ -62,7 +63,7 @@
|
||||
<div class="form-group">
|
||||
<label for="type" class="col-md-3 control-label">Type</label>
|
||||
<div class="col-md-8">
|
||||
<select class="form-control" id="type" name="type" onchange="javascript:updateForm(this)">
|
||||
<select class="form-control" id="type" name="type" onchange="javascript:updateAction(this)">
|
||||
<% types.each { %>
|
||||
<option data-action="${it.action}" value="${it.id}" ${it.default==true ? ' selected' : ''}>${it.name}</option>
|
||||
<% } %>
|
||||
@@ -162,9 +163,14 @@
|
||||
</form>
|
||||
</div>
|
||||
<script>
|
||||
var updateForm = function(sel) {
|
||||
var updateAction = function(sel) {
|
||||
var selected = sel.options[sel.selectedIndex];
|
||||
sel.form.action = selected.getAttribute("data-action");
|
||||
};
|
||||
var updateBaseDir = function() {
|
||||
var artifactId = document.getElementById("artifactId");
|
||||
var baseDir = document.getElementById("baseDir");
|
||||
baseDir.value = artifactId.value
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
|
||||
@@ -205,6 +205,15 @@ class ProjectGeneratorTests {
|
||||
.doesNotContain('@EnableAutoConfiguration', '@Configuration', '@ComponentScan')
|
||||
}
|
||||
|
||||
@Test
|
||||
void customBaseDirectory() {
|
||||
def request = createProjectRequest()
|
||||
request.baseDir = 'my-project'
|
||||
generateProject(request).hasBaseDir('my-project')
|
||||
.isJavaProject()
|
||||
.isMavenProject()
|
||||
}
|
||||
|
||||
PomAssert generateMavenPom(ProjectRequest request) {
|
||||
def content = new String(projectGenerator.generateMavenPom(request))
|
||||
new PomAssert(content).validateProjectRequest(request)
|
||||
|
||||
@@ -19,6 +19,7 @@ package io.spring.initializr.test
|
||||
import io.spring.initializr.InitializrMetadata
|
||||
|
||||
import static org.junit.Assert.assertEquals
|
||||
import static org.junit.Assert.assertTrue
|
||||
|
||||
/**
|
||||
* Various project based assertions.
|
||||
@@ -40,6 +41,21 @@ class ProjectAssert {
|
||||
this.dir = dir
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate that the project contains a base directory with the specified name.
|
||||
* <p>When extracting such archive, a directory with the specified {@code name}
|
||||
* will be created with the content of the project instead of extracting it in
|
||||
* the directory itself.
|
||||
* @param name the expected name of the base directory
|
||||
* @return an updated project assert on that base directory
|
||||
*/
|
||||
ProjectAssert hasBaseDir(String name) {
|
||||
File projectDir = file(name)
|
||||
assertTrue "No directory $name found in $dir.absolutePath", projectDir.exists()
|
||||
assertTrue "$name is not a directory", projectDir.isDirectory()
|
||||
new ProjectAssert(projectDir) // Replacing the root dir so that other assertions match the root
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a {@link PomAssert} for this project.
|
||||
*/
|
||||
|
||||
@@ -67,7 +67,7 @@ abstract class AbstractInitializerControllerFormIntegrationTests extends Abstrac
|
||||
@Test
|
||||
void createDefaultJavaProject() {
|
||||
def page = home()
|
||||
def projectAssert = zipProjectAssert(page.generateProject().contentAsStream.bytes)
|
||||
def projectAssert = zipProjectAssert(page, page.generateProject())
|
||||
projectAssert.isMavenProject().isJavaProject().hasStaticAndTemplatesResources(false)
|
||||
.pomAssert().hasDependenciesCount(2)
|
||||
.hasSpringBootStarterRootDependency().hasSpringBootStarterDependency('test')
|
||||
@@ -77,7 +77,7 @@ abstract class AbstractInitializerControllerFormIntegrationTests extends Abstrac
|
||||
void createDefaultGroovyProject() {
|
||||
def page = home()
|
||||
page.language = 'groovy'
|
||||
def projectAssert = zipProjectAssert(page.generateProject().contentAsStream.bytes)
|
||||
def projectAssert = zipProjectAssert(page, page.generateProject())
|
||||
projectAssert.isMavenProject().isGroovyProject().hasStaticAndTemplatesResources(false)
|
||||
.pomAssert().hasDependenciesCount(3)
|
||||
.hasSpringBootStarterRootDependency().hasSpringBootStarterDependency('test')
|
||||
@@ -92,7 +92,7 @@ abstract class AbstractInitializerControllerFormIntegrationTests extends Abstrac
|
||||
String value = webResponse.getResponseHeaderValue('Content-Disposition')
|
||||
assertEquals 'attachment; filename="foo-bar.zip"', value
|
||||
|
||||
def projectAssert = zipProjectAssert(webResponse)
|
||||
def projectAssert = zipProjectAssert(page, webResponse)
|
||||
projectAssert.isMavenProject().isJavaProject('MyProjectApplication')
|
||||
.hasStaticAndTemplatesResources(true)
|
||||
|
||||
@@ -108,7 +108,7 @@ abstract class AbstractInitializerControllerFormIntegrationTests extends Abstrac
|
||||
String value = webResponse.getResponseHeaderValue('Content-Disposition')
|
||||
assertEquals 'attachment; filename="foo-bar.zip"', value
|
||||
|
||||
def projectAssert = zipProjectAssert(webResponse)
|
||||
def projectAssert = zipProjectAssert(page, webResponse)
|
||||
projectAssert.isMavenProject().isGroovyProject('MyProjectApplication')
|
||||
.hasStaticAndTemplatesResources(true)
|
||||
|
||||
@@ -141,7 +141,7 @@ abstract class AbstractInitializerControllerFormIntegrationTests extends Abstrac
|
||||
void createWarProject() {
|
||||
def page = home()
|
||||
page.packaging = 'war'
|
||||
def projectAssert = zipProjectAssert(page.generateProject())
|
||||
def projectAssert = zipProjectAssert(page, page.generateProject())
|
||||
projectAssert.isMavenProject().isJavaWarProject()
|
||||
.pomAssert().hasPackaging('war').hasDependenciesCount(3)
|
||||
.hasSpringBootStarterDependency('web') // Added with war packaging
|
||||
@@ -153,7 +153,7 @@ abstract class AbstractInitializerControllerFormIntegrationTests extends Abstrac
|
||||
def page = home()
|
||||
page.type = projectType
|
||||
page.dependencies << 'data-jpa'
|
||||
def projectAssert = zipProjectAssert(page.generateProject())
|
||||
def projectAssert = zipProjectAssert(page, page.generateProject())
|
||||
projectAssert.isGradleProject().isJavaProject().hasStaticAndTemplatesResources(false)
|
||||
}
|
||||
|
||||
@@ -163,7 +163,10 @@ abstract class AbstractInitializerControllerFormIntegrationTests extends Abstrac
|
||||
createHomePage(home)
|
||||
}
|
||||
|
||||
ProjectAssert zipProjectAssert(WebResponse webResponse) {
|
||||
/**
|
||||
* Initialize a {@link ProjectAssert} for the specified {@link HomePage} and {@link WebResponse}.
|
||||
*/
|
||||
protected ProjectAssert zipProjectAssert(HomePage page, WebResponse webResponse) {
|
||||
zipProjectAssert(webResponse.contentAsStream.bytes)
|
||||
}
|
||||
|
||||
|
||||
@@ -16,7 +16,10 @@
|
||||
|
||||
package io.spring.initializr.web
|
||||
|
||||
import com.gargoylesoftware.htmlunit.WebResponse
|
||||
import com.gargoylesoftware.htmlunit.html.HtmlPage
|
||||
import io.spring.initializr.InitializrMetadata
|
||||
import io.spring.initializr.test.ProjectAssert
|
||||
import io.spring.initializr.web.support.DefaultHomePage
|
||||
import io.spring.initializr.web.support.HomePage
|
||||
|
||||
@@ -27,7 +30,6 @@ import io.spring.initializr.web.support.HomePage
|
||||
*/
|
||||
class MainControllerFormIntegrationTests extends AbstractInitializerControllerFormIntegrationTests {
|
||||
|
||||
|
||||
@Override
|
||||
void createSimpleGradleProject() {
|
||||
createSimpleGradleProject('gradle-project')
|
||||
@@ -43,4 +45,12 @@ class MainControllerFormIntegrationTests extends AbstractInitializerControllerFo
|
||||
new DefaultHomePage(home)
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ProjectAssert zipProjectAssert(HomePage page, WebResponse webResponse) {
|
||||
ProjectAssert projectAssert = super.zipProjectAssert(page, webResponse)
|
||||
// we require self contained archive by default
|
||||
String dirName = page.artifactId ?: InitializrMetadata.Defaults.DEFAULT_NAME
|
||||
projectAssert.hasBaseDir(dirName)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user