Lots of work refactoring and introduction of StaticSiteGenerator and implementation.
This commit is contained in:
parent
7708ac66e0
commit
5a70f9c91c
2
TODO.md
2
TODO.md
@ -8,6 +8,7 @@ Here will be kept all of the various todos for this project, organized by releas
|
|||||||
- [ ] Plan out plugin system such that we can create custom providers of texts, data, etc.
|
- [ ] Plan out plugin system such that we can create custom providers of texts, data, etc.
|
||||||
- [ ] Provide a way to override `ssgBuilds` variables from the cli.
|
- [ ] Provide a way to override `ssgBuilds` variables from the cli.
|
||||||
- [ ] Add `Watchable` interface/trait back; an abstraction over FS watching and other sources (such as a database, etc.).
|
- [ ] Add `Watchable` interface/trait back; an abstraction over FS watching and other sources (such as a database, etc.).
|
||||||
|
- [ ] Explore `apply(Plugin)` in buildScripts.
|
||||||
|
|
||||||
### Fix
|
### Fix
|
||||||
|
|
||||||
@ -18,6 +19,7 @@ Here will be kept all of the various todos for this project, organized by releas
|
|||||||
- [x] Remove `lib` module.
|
- [x] Remove `lib` module.
|
||||||
- [ ] Add a way for CLI to choose a build to do, or multiple builds, defaulting to 'default' if it exists.
|
- [ ] Add a way for CLI to choose a build to do, or multiple builds, defaulting to 'default' if it exists.
|
||||||
- [ ] Write lots of tests for buildscript dsl, etc.
|
- [ ] Write lots of tests for buildscript dsl, etc.
|
||||||
|
- [ ] Explore `base` in buildScript dsl.
|
||||||
|
|
||||||
### Fix
|
### Fix
|
||||||
- [ ] Update CHANGELOG to reflect the gsp-dsl changes.
|
- [ ] Update CHANGELOG to reflect the gsp-dsl changes.
|
||||||
|
@ -0,0 +1,104 @@
|
|||||||
|
package com.jessebrault.ssg
|
||||||
|
|
||||||
|
import com.jessebrault.ssg.buildscript.Build
|
||||||
|
import com.jessebrault.ssg.buildscript.BuildScriptConfiguratorFactory
|
||||||
|
import com.jessebrault.ssg.buildscript.BuildScriptRunner
|
||||||
|
import com.jessebrault.ssg.util.Diagnostic
|
||||||
|
import org.slf4j.Logger
|
||||||
|
import org.slf4j.LoggerFactory
|
||||||
|
import org.slf4j.Marker
|
||||||
|
import org.slf4j.MarkerFactory
|
||||||
|
|
||||||
|
import java.util.function.Consumer
|
||||||
|
|
||||||
|
final class BuildScriptBasedStaticSiteGenerator implements StaticSiteGenerator {
|
||||||
|
|
||||||
|
private static final Logger logger = LoggerFactory.getLogger(BuildScriptBasedStaticSiteGenerator)
|
||||||
|
private static final Marker enter = MarkerFactory.getMarker('enter')
|
||||||
|
private static final Marker exit = MarkerFactory.getMarker('exit')
|
||||||
|
|
||||||
|
private final BuildScriptRunner buildScriptRunner
|
||||||
|
private final BuildScriptConfiguratorFactory configuratorFactory
|
||||||
|
private final File buildScript
|
||||||
|
private final Collection<File> buildSrcDirs
|
||||||
|
private final Map<String, Object> scriptArgs
|
||||||
|
|
||||||
|
private final Collection<Build> builds = []
|
||||||
|
|
||||||
|
private boolean ranBuildScript = false
|
||||||
|
|
||||||
|
BuildScriptBasedStaticSiteGenerator(
|
||||||
|
BuildScriptRunner buildScriptRunner,
|
||||||
|
BuildScriptConfiguratorFactory configuratorFactory,
|
||||||
|
File buildScript = null,
|
||||||
|
Collection<File> buildSrcDirs = [],
|
||||||
|
Map<String, Object> scriptArgs = [:]
|
||||||
|
) {
|
||||||
|
this.buildScriptRunner = buildScriptRunner
|
||||||
|
this.configuratorFactory = configuratorFactory
|
||||||
|
this.buildScript = buildScript
|
||||||
|
this.buildSrcDirs = buildSrcDirs
|
||||||
|
this.scriptArgs = scriptArgs
|
||||||
|
}
|
||||||
|
|
||||||
|
private void runBuildScript() {
|
||||||
|
logger.trace(enter, '')
|
||||||
|
|
||||||
|
if (this.buildScript == null) {
|
||||||
|
logger.info('no specified build script; using defaults')
|
||||||
|
def result = this.buildScriptRunner.runBuildScript {
|
||||||
|
this.configuratorFactory.get().accept(it)
|
||||||
|
}
|
||||||
|
this.builds.addAll(result)
|
||||||
|
} else if (this.buildScript.exists() && this.buildScript.isFile()) {
|
||||||
|
logger.info('running buildScript: {}', this.buildScript)
|
||||||
|
def result = this.buildScriptRunner.runBuildScript(
|
||||||
|
this.buildScript.name,
|
||||||
|
this.buildScript.parentFile.toURI().toURL(),
|
||||||
|
this.buildSrcDirs.collect { it.toURI().toURL() },
|
||||||
|
[args: this.scriptArgs]
|
||||||
|
) {
|
||||||
|
this.configuratorFactory.get().accept(it)
|
||||||
|
}
|
||||||
|
this.builds.addAll(result)
|
||||||
|
} else {
|
||||||
|
throw new IllegalArgumentException("given buildScript ${ this.buildScript } either does not exist or is not a file")
|
||||||
|
}
|
||||||
|
this.ranBuildScript = true
|
||||||
|
|
||||||
|
logger.trace(exit, '')
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
boolean doBuild(String buildName, Consumer<Collection<Diagnostic>> diagnosticsConsumer = { }) {
|
||||||
|
logger.trace(enter, 'buildName: {}, diagnosticsConsumer: {}', buildName, diagnosticsConsumer)
|
||||||
|
|
||||||
|
if (!this.ranBuildScript) {
|
||||||
|
this.runBuildScript()
|
||||||
|
}
|
||||||
|
|
||||||
|
def build = this.builds.find { it.name == buildName }
|
||||||
|
if (!build) {
|
||||||
|
throw new IllegalArgumentException("there is no registered build with name: ${ buildName }")
|
||||||
|
}
|
||||||
|
|
||||||
|
def buildTasksConverter = new SimpleBuildTasksConverter()
|
||||||
|
def successful = true
|
||||||
|
def tasksResult = buildTasksConverter.convert(build)
|
||||||
|
if (tasksResult.hasDiagnostics()) {
|
||||||
|
successful = false
|
||||||
|
diagnosticsConsumer.accept(tasksResult.diagnostics)
|
||||||
|
} else {
|
||||||
|
def tasks = tasksResult.get()
|
||||||
|
def taskDiagnostics = tasks.collectMany { it.execute(tasks) }
|
||||||
|
if (!taskDiagnostics.isEmpty()) {
|
||||||
|
successful = false
|
||||||
|
diagnosticsConsumer.accept(taskDiagnostics)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.trace(exit, 'successful: {}', successful)
|
||||||
|
successful
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,9 @@
|
|||||||
|
package com.jessebrault.ssg
|
||||||
|
|
||||||
|
import com.jessebrault.ssg.util.Diagnostic
|
||||||
|
|
||||||
|
import java.util.function.Consumer
|
||||||
|
|
||||||
|
interface StaticSiteGenerator {
|
||||||
|
boolean doBuild(String buildName, Consumer<Collection<Diagnostic>> diagnosticsConsumer)
|
||||||
|
}
|
@ -1,5 +1,8 @@
|
|||||||
package com.jessebrault.ssg.buildscript
|
package com.jessebrault.ssg.buildscript
|
||||||
|
|
||||||
|
import groovy.transform.stc.ClosureParams
|
||||||
|
import groovy.transform.stc.SimpleType
|
||||||
|
|
||||||
import java.util.function.Consumer
|
import java.util.function.Consumer
|
||||||
|
|
||||||
interface BuildScriptRunner {
|
interface BuildScriptRunner {
|
||||||
@ -12,6 +15,12 @@ interface BuildScriptRunner {
|
|||||||
Consumer<BuildScriptBase> configureBuildScript
|
Consumer<BuildScriptBase> configureBuildScript
|
||||||
)
|
)
|
||||||
|
|
||||||
|
Collection<Build> runBuildScript(
|
||||||
|
@DelegatesTo(value = BuildScriptBase, strategy = Closure.DELEGATE_FIRST)
|
||||||
|
@ClosureParams(value = SimpleType, options = 'com.jessebrault.ssg.buildscript.BuildScriptBase')
|
||||||
|
Closure<?> scriptBody
|
||||||
|
)
|
||||||
|
|
||||||
default Collection<Build> runBuildScript(
|
default Collection<Build> runBuildScript(
|
||||||
String scriptName,
|
String scriptName,
|
||||||
URL scriptBaseDirUrl,
|
URL scriptBaseDirUrl,
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
package com.jessebrault.ssg.buildscript
|
package com.jessebrault.ssg.buildscript
|
||||||
|
|
||||||
import groovy.transform.NullCheck
|
import groovy.transform.NullCheck
|
||||||
|
import groovy.transform.stc.ClosureParams
|
||||||
|
import groovy.transform.stc.SimpleType
|
||||||
import org.codehaus.groovy.control.CompilerConfiguration
|
import org.codehaus.groovy.control.CompilerConfiguration
|
||||||
|
|
||||||
import java.util.function.Consumer
|
import java.util.function.Consumer
|
||||||
@ -29,4 +31,24 @@ final class SimpleBuildScriptRunner implements BuildScriptRunner {
|
|||||||
buildScript.getBuilds()
|
buildScript.getBuilds()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
Collection<Build> runBuildScript(
|
||||||
|
@DelegatesTo(value = BuildScriptBase, strategy = Closure.DELEGATE_FIRST)
|
||||||
|
@ClosureParams(value = SimpleType, options = 'com.jessebrault.ssg.buildscript.BuildScriptBase')
|
||||||
|
Closure<?> scriptBody
|
||||||
|
) {
|
||||||
|
def base = new BuildScriptBase() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
Object run() {
|
||||||
|
scriptBody.delegate = this
|
||||||
|
scriptBody.resolveStrategy = Closure.DELEGATE_FIRST
|
||||||
|
scriptBody.call(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
base.run()
|
||||||
|
base.getBuilds()
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -30,7 +30,7 @@ final class FileBasedCollectionProvider<T> extends AbstractCollectionProvider<T>
|
|||||||
@Override
|
@Override
|
||||||
Collection<T> provide() {
|
Collection<T> provide() {
|
||||||
if (!this.baseDirectory.isDirectory()) {
|
if (!this.baseDirectory.isDirectory()) {
|
||||||
logger.error('{} does not exist or is not a directory; returning empty collection', this.baseDirectory)
|
logger.warn('{} does not exist or is not a directory; returning empty collection', this.baseDirectory)
|
||||||
[]
|
[]
|
||||||
} else {
|
} else {
|
||||||
final Collection<T> ts = []
|
final Collection<T> ts = []
|
||||||
|
@ -0,0 +1,60 @@
|
|||||||
|
package com.jessebrault.ssg
|
||||||
|
|
||||||
|
import com.jessebrault.ssg.buildscript.BuildScriptBase
|
||||||
|
import com.jessebrault.ssg.buildscript.BuildScriptConfiguratorFactory
|
||||||
|
import com.jessebrault.ssg.buildscript.SimpleBuildScriptRunner
|
||||||
|
import com.jessebrault.ssg.util.FileUtil
|
||||||
|
import org.junit.jupiter.api.Test
|
||||||
|
import org.slf4j.Logger
|
||||||
|
import org.slf4j.LoggerFactory
|
||||||
|
|
||||||
|
import java.util.function.Consumer
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertTrue
|
||||||
|
|
||||||
|
// TODO: everything is working, now to expand this and refactor out common test code.
|
||||||
|
final class BuildScriptBasedStaticSiteGeneratorTests {
|
||||||
|
|
||||||
|
private static final Logger logger = LoggerFactory.getLogger(BuildScriptBasedStaticSiteGeneratorTests)
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void buildWithOneTextAndTemplate() {
|
||||||
|
def sourceDir = File.createTempDir()
|
||||||
|
|
||||||
|
def buildScript = new File(sourceDir, 'build.groovy')
|
||||||
|
FileUtil.copyResourceToFile('oneTextAndTemplate.groovy', buildScript)
|
||||||
|
|
||||||
|
new FileTreeBuilder(sourceDir).tap {
|
||||||
|
dir('texts') {
|
||||||
|
file('hello.md', '---\ntemplate: hello.gsp\n---\nHello, World!')
|
||||||
|
}
|
||||||
|
dir('templates') {
|
||||||
|
file('hello.gsp', '<%= text.render() %>')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
def ssg = new BuildScriptBasedStaticSiteGenerator(
|
||||||
|
new SimpleBuildScriptRunner(),
|
||||||
|
new BuildScriptConfiguratorFactory() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
Consumer<BuildScriptBase> get() {
|
||||||
|
return { }
|
||||||
|
}
|
||||||
|
|
||||||
|
},
|
||||||
|
buildScript,
|
||||||
|
[],
|
||||||
|
[sourceDir: sourceDir]
|
||||||
|
)
|
||||||
|
assertTrue(ssg.doBuild('test') {
|
||||||
|
it.each { logger.error(it.toString()) }
|
||||||
|
})
|
||||||
|
|
||||||
|
def expectedBase = File.createTempDir()
|
||||||
|
new File(expectedBase, 'hello.html').write('<p>Hello, World!</p>\n')
|
||||||
|
|
||||||
|
FileUtil.assertFileStructureAndContents(expectedBase, new File(sourceDir, 'build'))
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -17,6 +17,8 @@ final class SimpleBuildScriptRunnerTests {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Must be non-static, otherwise Groovy gets confused inside the Closures.
|
* Must be non-static, otherwise Groovy gets confused inside the Closures.
|
||||||
|
*
|
||||||
|
* TODO: use the FileUtil.copyResourceToWriter method
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings('GrMethodMayBeStatic')
|
@SuppressWarnings('GrMethodMayBeStatic')
|
||||||
private void copyLocalResourceToWriter(String name, Writer target) {
|
private void copyLocalResourceToWriter(String name, Writer target) {
|
||||||
@ -95,4 +97,14 @@ final class SimpleBuildScriptRunnerTests {
|
|||||||
verify(stringConsumer).accept('test')
|
verify(stringConsumer).accept('test')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void customScript() {
|
||||||
|
def runner = new SimpleBuildScriptRunner()
|
||||||
|
def result = runner.runBuildScript {
|
||||||
|
build('test') { }
|
||||||
|
}
|
||||||
|
assertEquals(1, result.size())
|
||||||
|
assertEquals('test', result[0].name)
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
48
api/src/test/resources/oneTextAndTemplate.groovy
Normal file
48
api/src/test/resources/oneTextAndTemplate.groovy
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
import com.jessebrault.ssg.buildscript.Build
|
||||||
|
import com.jessebrault.ssg.buildscript.BuildScriptBase
|
||||||
|
import com.jessebrault.ssg.buildscript.OutputDir
|
||||||
|
import com.jessebrault.ssg.html.TextToHtmlSpec
|
||||||
|
import com.jessebrault.ssg.html.TextToHtmlTaskFactory
|
||||||
|
import com.jessebrault.ssg.provider.CollectionProviders
|
||||||
|
import com.jessebrault.ssg.template.TemplateTypes
|
||||||
|
import com.jessebrault.ssg.template.TemplatesProviders
|
||||||
|
import com.jessebrault.ssg.text.TextTypes
|
||||||
|
import com.jessebrault.ssg.text.TextsProviders
|
||||||
|
import com.jessebrault.ssg.util.ExtensionUtil
|
||||||
|
import com.jessebrault.ssg.util.Result
|
||||||
|
import groovy.transform.BaseScript
|
||||||
|
|
||||||
|
@BaseScript
|
||||||
|
BuildScriptBase base
|
||||||
|
|
||||||
|
build('test') {
|
||||||
|
outputDirFunction = { Build b -> new OutputDir(new File(args.sourceDir, 'build')) }
|
||||||
|
|
||||||
|
types {
|
||||||
|
textTypes << TextTypes.MARKDOWN
|
||||||
|
templateTypes << TemplateTypes.GSP
|
||||||
|
}
|
||||||
|
providers { types ->
|
||||||
|
texts TextsProviders.from(new File(args.sourceDir, 'texts'), types.textTypes)
|
||||||
|
templates TemplatesProviders.from(new File(args.sourceDir, 'templates'), types.templateTypes)
|
||||||
|
}
|
||||||
|
taskFactories { sources ->
|
||||||
|
register('textToHtml', TextToHtmlTaskFactory::new) {
|
||||||
|
it.specProvider += CollectionProviders.fromSupplier {
|
||||||
|
def templates = sources.templatesProvider.provide()
|
||||||
|
return sources.textsProvider.provide().collect {
|
||||||
|
def frontMatterResult = it.type.frontMatterGetter.get(it)
|
||||||
|
if (frontMatterResult.hasDiagnostics()) {
|
||||||
|
return Result.ofDiagnostics(frontMatterResult.diagnostics)
|
||||||
|
}
|
||||||
|
def desiredTemplate = frontMatterResult.get().get('template')
|
||||||
|
def template = templates.find { it.path == desiredTemplate }
|
||||||
|
if (template == null) {
|
||||||
|
throw new IllegalArgumentException('template is null')
|
||||||
|
}
|
||||||
|
return Result.of(new TextToHtmlSpec(it, template, ExtensionUtil.stripExtension(it.path) + '.html'))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,65 @@
|
|||||||
|
package com.jessebrault.ssg.util
|
||||||
|
|
||||||
|
import org.slf4j.Logger
|
||||||
|
import org.slf4j.LoggerFactory
|
||||||
|
|
||||||
|
import java.nio.file.Path
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertEquals
|
||||||
|
|
||||||
|
final class FileUtil {
|
||||||
|
|
||||||
|
private static final Logger logger = LoggerFactory.getLogger(FileUtil)
|
||||||
|
|
||||||
|
private static Map<String, Object> fileToMap(File file) {
|
||||||
|
[
|
||||||
|
type: file.isDirectory() ? 'directory' : (file.isFile() ? 'file' : null),
|
||||||
|
text: file.file ? file.text : null
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
static void assertFileStructureAndContents(
|
||||||
|
File expectedBaseDir,
|
||||||
|
File actualBaseDir
|
||||||
|
) {
|
||||||
|
final Map<Path, File> expectedPathsAndFiles = [:]
|
||||||
|
def expectedBasePath = expectedBaseDir.toPath()
|
||||||
|
expectedBaseDir.eachFileRecurse {
|
||||||
|
def relativePath = expectedBasePath.relativize(it.toPath())
|
||||||
|
expectedPathsAndFiles[relativePath] = it
|
||||||
|
}
|
||||||
|
logger.debug('expectedPaths: {}', expectedPathsAndFiles.keySet())
|
||||||
|
|
||||||
|
expectedPathsAndFiles.forEach { relativePath, expectedFile ->
|
||||||
|
def actualFile = new File(actualBaseDir, relativePath.toString())
|
||||||
|
logger.debug(
|
||||||
|
'relativePath: {}, expectedFile: {}, actualFile: {}',
|
||||||
|
relativePath,
|
||||||
|
fileToMap(expectedFile),
|
||||||
|
fileToMap(actualFile)
|
||||||
|
)
|
||||||
|
assertEquals(expectedFile.directory, actualFile.directory)
|
||||||
|
assertEquals(expectedFile.file, actualFile.file)
|
||||||
|
if (expectedFile.file) {
|
||||||
|
assertEquals(expectedFile.text, actualFile.text)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void copyResourceToWriter(String name, Writer target) {
|
||||||
|
FileUtil.getClassLoader().getResourceAsStream(name).withReader {
|
||||||
|
it.transferTo(target)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void copyResourceToFile(String name, File target) {
|
||||||
|
FileUtil.getClassLoader().getResourceAsStream(name).withReader { Reader reader ->
|
||||||
|
target.withWriter { Writer writer ->
|
||||||
|
reader.transferTo(writer)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private FileUtil() {}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,42 @@
|
|||||||
|
package com.jessebrault.ssg.util
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Test
|
||||||
|
|
||||||
|
import static com.jessebrault.ssg.util.FileUtil.assertFileStructureAndContents
|
||||||
|
import static com.jessebrault.ssg.util.FileUtil.copyResourceToFile
|
||||||
|
import static com.jessebrault.ssg.util.FileUtil.copyResourceToWriter
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertEquals
|
||||||
|
|
||||||
|
final class FileUtilTests {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void sameStructureAndContentsTest() {
|
||||||
|
def b0 = File.createTempDir()
|
||||||
|
def b1 = File.createTempDir()
|
||||||
|
[b0, b1].each {
|
||||||
|
new FileTreeBuilder(it).tap {
|
||||||
|
file('testFile', 'test content')
|
||||||
|
dir('testDir') {
|
||||||
|
file('testNestedFile', 'test content')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
assertFileStructureAndContents(b0, b1)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void copyResourceToWriterTest() {
|
||||||
|
def writer = new StringWriter()
|
||||||
|
copyResourceToWriter('testResource.txt', writer)
|
||||||
|
assertEquals('Hello, World!', writer.toString())
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void copyResourceToTargetFileTest() {
|
||||||
|
def tempDir = File.createTempDir()
|
||||||
|
def target = new File(tempDir, 'testResource.txt')
|
||||||
|
copyResourceToFile('testResource.txt', target)
|
||||||
|
assertEquals('Hello, World!', target.text)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
17
api/src/testFixtures/resources/log4j2.xml
Normal file
17
api/src/testFixtures/resources/log4j2.xml
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" ?>
|
||||||
|
<Configuration name="ssg" status="WARN">
|
||||||
|
<Appenders>
|
||||||
|
<Console name="standard" target="SYSTEM_OUT">
|
||||||
|
<PatternLayout>
|
||||||
|
<MarkerPatternSelector defaultPattern="%highlight{%-5level} %logger{1}: %msg%n%ex">
|
||||||
|
<PatternMatch key="FLOW" pattern="%highlight{%-5level} %logger{1}: %markerSimpleName %msg%n%ex" />
|
||||||
|
</MarkerPatternSelector>
|
||||||
|
</PatternLayout>
|
||||||
|
</Console>
|
||||||
|
</Appenders>
|
||||||
|
<Loggers>
|
||||||
|
<Root level="trace">
|
||||||
|
<AppenderRef ref="standard" />
|
||||||
|
</Root>
|
||||||
|
</Loggers>
|
||||||
|
</Configuration>
|
1
api/src/testFixtures/resources/testResource.txt
Normal file
1
api/src/testFixtures/resources/testResource.txt
Normal file
@ -0,0 +1 @@
|
|||||||
|
Hello, World!
|
@ -52,6 +52,12 @@ dependencies {
|
|||||||
|
|
||||||
// https://mvnrepository.com/artifact/org.apache.logging.log4j/log4j-core
|
// https://mvnrepository.com/artifact/org.apache.logging.log4j/log4j-core
|
||||||
testRuntimeOnly 'org.apache.logging.log4j:log4j-core:2.19.0'
|
testRuntimeOnly 'org.apache.logging.log4j:log4j-core:2.19.0'
|
||||||
|
|
||||||
|
// https://mvnrepository.com/artifact/org.apache.logging.log4j/log4j-slf4j-impl
|
||||||
|
testFixturesRuntimeOnly 'org.apache.logging.log4j:log4j-slf4j-impl:2.19.0'
|
||||||
|
|
||||||
|
// https://mvnrepository.com/artifact/org.apache.logging.log4j/log4j-core
|
||||||
|
testFixturesRuntimeOnly 'org.apache.logging.log4j:log4j-core:2.19.0'
|
||||||
}
|
}
|
||||||
|
|
||||||
test {
|
test {
|
||||||
|
@ -1,8 +1,7 @@
|
|||||||
package com.jessebrault.ssg
|
package com.jessebrault.ssg
|
||||||
|
|
||||||
import com.jessebrault.ssg.buildscript.Build
|
|
||||||
import com.jessebrault.ssg.buildscript.SimpleBuildScriptRunner
|
|
||||||
import com.jessebrault.ssg.buildscript.DefaultBuildScriptConfiguratorFactory
|
import com.jessebrault.ssg.buildscript.DefaultBuildScriptConfiguratorFactory
|
||||||
|
import com.jessebrault.ssg.buildscript.SimpleBuildScriptRunner
|
||||||
import com.jessebrault.ssg.util.Diagnostic
|
import com.jessebrault.ssg.util.Diagnostic
|
||||||
import org.apache.logging.log4j.LogManager
|
import org.apache.logging.log4j.LogManager
|
||||||
import org.apache.logging.log4j.Logger
|
import org.apache.logging.log4j.Logger
|
||||||
@ -12,7 +11,26 @@ abstract class AbstractBuildCommand extends AbstractSubCommand {
|
|||||||
|
|
||||||
private static final Logger logger = LogManager.getLogger(AbstractBuildCommand)
|
private static final Logger logger = LogManager.getLogger(AbstractBuildCommand)
|
||||||
|
|
||||||
protected Collection<Build> availableBuilds = []
|
@CommandLine.Option(
|
||||||
|
names = ['-s', '--script', '--buildScript'],
|
||||||
|
description = 'The build script file to execute.'
|
||||||
|
)
|
||||||
|
protected File buildScript = null
|
||||||
|
|
||||||
|
@CommandLine.Option(
|
||||||
|
names = '--scriptArgs',
|
||||||
|
description = 'Named argument(s) to pass directly to the build script.',
|
||||||
|
split = ','
|
||||||
|
)
|
||||||
|
protected Map<String, String> scriptArgs = [:]
|
||||||
|
|
||||||
|
@CommandLine.Option(
|
||||||
|
names = '--buildSrcDirs',
|
||||||
|
description = 'Path(s) to director(ies) containing Groovy classes and scripts which should be visible to the main build script.',
|
||||||
|
split = ',',
|
||||||
|
paramLabel = 'buildSrcDir'
|
||||||
|
)
|
||||||
|
protected Collection<File> buildSrcDirs = [new File('buildSrc')]
|
||||||
|
|
||||||
@CommandLine.Option(
|
@CommandLine.Option(
|
||||||
names = ['-b', '--build'],
|
names = ['-b', '--build'],
|
||||||
@ -21,57 +39,28 @@ abstract class AbstractBuildCommand extends AbstractSubCommand {
|
|||||||
)
|
)
|
||||||
protected Collection<String> requestedBuilds = ['default']
|
protected Collection<String> requestedBuilds = ['default']
|
||||||
|
|
||||||
@CommandLine.Option(
|
protected StaticSiteGenerator staticSiteGenerator = null
|
||||||
names = ['-s', '--script', '--buildScript'],
|
|
||||||
description = 'The build script file to execute.',
|
|
||||||
paramLabel = 'buildScript'
|
|
||||||
)
|
|
||||||
void setBuildFile(File buildScriptFile) {
|
|
||||||
if (buildScriptFile == null) {
|
|
||||||
buildScriptFile = new File('ssgBuilds.groovy')
|
|
||||||
}
|
|
||||||
if (buildScriptFile.exists()) {
|
|
||||||
logger.info('found buildScriptFile: {}', buildScriptFile)
|
|
||||||
def configuratorFactory = new DefaultBuildScriptConfiguratorFactory()
|
|
||||||
this.availableBuilds = new SimpleBuildScriptRunner().runBuildScript(
|
|
||||||
buildScriptFile.name,
|
|
||||||
buildScriptFile.parentFile.toURI().toURL(),
|
|
||||||
[new File('buildSrc').toURI().toURL()],
|
|
||||||
[:]
|
|
||||||
) {
|
|
||||||
configuratorFactory.get().accept(it)
|
|
||||||
}
|
|
||||||
logger.debug('after running buildScriptFile {}, builds: {}', buildScriptFile, this.availableBuilds)
|
|
||||||
} else {
|
|
||||||
throw new IllegalArgumentException(
|
|
||||||
"buildScriptFile file ${ buildScriptFile } does not exist or could not be found."
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected final Integer doBuild(String requestedBuild) {
|
protected final Integer doSingleBuild(String requestedBuild) {
|
||||||
logger.traceEntry('requestedBuild: {}', requestedBuild)
|
logger.traceEntry('requestedBuild: {}', requestedBuild)
|
||||||
|
|
||||||
def buildTasksConverter = new SimpleBuildTasksConverter()
|
if (this.staticSiteGenerator == null) {
|
||||||
|
this.staticSiteGenerator = new BuildScriptBasedStaticSiteGenerator(
|
||||||
def build = this.availableBuilds.find { it.name == requestedBuild }
|
new SimpleBuildScriptRunner(),
|
||||||
|
new DefaultBuildScriptConfiguratorFactory(),
|
||||||
def hadDiagnostics = false
|
this.buildScript,
|
||||||
def tasksResult = buildTasksConverter.convert(build)
|
this.buildSrcDirs,
|
||||||
if (tasksResult.hasDiagnostics()) {
|
this.scriptArgs
|
||||||
hadDiagnostics = true
|
)
|
||||||
tasksResult.diagnostics.each { logger.error(it.message) }
|
|
||||||
} else {
|
|
||||||
def tasks = tasksResult.get()
|
|
||||||
Collection<Diagnostic> taskDiagnostics = []
|
|
||||||
tasks.each { it.execute(tasks) }
|
|
||||||
if (!taskDiagnostics.isEmpty()) {
|
|
||||||
hadDiagnostics = true
|
|
||||||
taskDiagnostics.each { logger.error(it.message) }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.traceExit(hadDiagnostics ? 1 : 0)
|
final Collection<Diagnostic> diagnostics = []
|
||||||
|
if (!this.staticSiteGenerator.doBuild(requestedBuild, diagnostics.&addAll)) {
|
||||||
|
diagnostics.each { logger.warn(it) }
|
||||||
|
logger.traceExit(1)
|
||||||
|
} else {
|
||||||
|
logger.traceExit(0)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -18,7 +18,7 @@ final class SsgBuild extends AbstractBuildCommand {
|
|||||||
logger.traceEntry()
|
logger.traceEntry()
|
||||||
def result = 0
|
def result = 0
|
||||||
this.requestedBuilds.each {
|
this.requestedBuilds.each {
|
||||||
def buildResult = this.doBuild(it)
|
def buildResult = this.doSingleBuild(it)
|
||||||
if (buildResult == 1) {
|
if (buildResult == 1) {
|
||||||
result = 1
|
result = 1
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user