Should be able to include builds.

This commit is contained in:
JesseBrault0709 2023-06-14 21:35:14 +02:00
parent c18438ff6a
commit f3c6f1ef3c
6 changed files with 155 additions and 24 deletions

View File

@ -3,7 +3,11 @@ 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.buildscript.BuildUtil
import com.jessebrault.ssg.util.Diagnostic
import groovy.transform.EqualsAndHashCode
import groovy.transform.NullCheck
import groovy.transform.TupleConstructor
import org.jetbrains.annotations.Nullable
import org.slf4j.Logger
import org.slf4j.LoggerFactory
@ -79,7 +83,15 @@ final class BuildScriptBasedStaticSiteGenerator implements StaticSiteGenerator {
Objects.requireNonNull(this.buildScriptClassLoader)
}
// TODO: cache
@TupleConstructor(defaults = false)
@NullCheck(includeGenerated = true)
@EqualsAndHashCode
private static final class IncludedBuildsResult {
final Collection<Build> builds
final Collection<Diagnostic> diagnostics
}
// TODO: cache build script results
@Override
boolean doBuild(
String buildName,
@ -96,23 +108,52 @@ final class BuildScriptBasedStaticSiteGenerator implements StaticSiteGenerator {
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)
def includedBuildsResult = build.includedBuilds.inject(
new IncludedBuildsResult([], [])
) { acc, includedBuildName ->
def includedBuild = this.builds.find { it.name == includedBuildName }
if (includedBuild == null) {
acc.diagnostics << new Diagnostic("There is no registered build ${ includedBuildName } that can be included.")
} else {
acc.builds << includedBuild
}
acc
}
logger.trace(exit, 'successful: {}', successful)
successful
if (includedBuildsResult.diagnostics.size() > 0) {
diagnosticsConsumer.accept(includedBuildsResult.diagnostics)
logger.trace(exit, 'result: false')
return false
}
def buildTasksConverter = new SimpleBuildTasksConverter()
def allBuilds = includedBuildsResult.builds + build
def allBuildsConvertResults = allBuilds.collect {
buildTasksConverter.convert(it)
}
def allBuildsConvertDiagnostics = allBuildsConvertResults.collectMany {
it.diagnostics
}
if (allBuildsConvertDiagnostics.size() > 0) {
diagnosticsConsumer.accept(allBuildsConvertDiagnostics)
logger.trace(exit, 'result: false')
return false
}
def allTasks = allBuildsConvertResults.collectMany {
it.get()
}
def allTasksDiagnostics = allTasks.collectMany { it.execute(allTasks) }
if (allTasksDiagnostics.size() > 0) {
diagnosticsConsumer.accept(allTasksDiagnostics)
logger.trace(exit, 'result: false')
return false
}
logger.trace(exit, 'result: true')
return true
}
}

View File

@ -20,6 +20,7 @@ final class Build {
OutputDirFunctions.DEFAULT,
SiteSpec.getBlank(),
[:],
[],
[]
)
}
@ -30,7 +31,8 @@ final class Build {
args.outputDirFunction as Function<Build, OutputDir> ?: OutputDirFunctions.DEFAULT,
args.siteSpec as SiteSpec ?: SiteSpec.getBlank(),
args.globals as Map<String, Object> ?: [:],
args.taskFactorySpecs as Collection<TaskFactorySpec<TaskFactory>> ?: []
args.taskFactorySpecs as Collection<TaskFactorySpec<TaskFactory>> ?: [],
args.includedBuilds as Collection<String> ?: []
)
}
@ -40,7 +42,8 @@ final class Build {
OutputDirFunctions.concat(b0.outputDirFunction, b1.outputDirFunction),
SiteSpec.concat(b0.siteSpec, b1.siteSpec),
b0.globals + b1.globals,
b0.taskFactorySpecs + b1.taskFactorySpecs
b0.taskFactorySpecs + b1.taskFactorySpecs,
b0.includedBuilds + b1.includedBuilds
)
}
@ -49,6 +52,7 @@ final class Build {
final SiteSpec siteSpec
final Map<String, Object> globals
final Collection<TaskFactorySpec<TaskFactory>> taskFactorySpecs
final Collection<String> includedBuilds
Build plus(Build other) {
concat(this, other)
@ -56,7 +60,7 @@ final class Build {
@Override
String toString() {
"Build(name: ${ this.name }, siteSpec: ${ this.siteSpec }, globals: ${ this.globals })"
"Build(name: ${ this.name }, siteSpec: ${ this.siteSpec }, globals: ${ this.globals }, includedBuilds: ${ this.includedBuilds })"
}
}

View File

@ -25,6 +25,10 @@ final class BuildSpecUtil {
m0 + m1
}
private static final Monoid<Collection<String>> includedBuildsMonoid = Monoids.of([]) { c0, c1 ->
c0 + c1
}
private static final Monoid<Collection<TaskFactorySpec<TaskFactory>>> taskFactoriesMonoid =
Monoids.getMergeCollectionMonoid(TaskFactorySpec.SAME_NAME_AND_SUPPLIER_EQ, TaskFactorySpec.DEFAULT_SEMIGROUP)
@ -76,12 +80,17 @@ final class BuildSpecUtil {
r.getTaskFactoriesResult(acc, true, taskFactoriesMonoid, sourcesResult)
}
new Build(
specs.last().name,
outputDirFunctionResult,
siteSpecResult,
globalsResult,
taskFactoriesResult
def includedBuildsResult = reduceResults(allResults, includedBuildsMonoid) { acc, r ->
r.getIncludedBuildsResult(acc, true, includedBuildsMonoid)
}
Build.get(
name: specs.last().name,
outputDirFunction: outputDirFunctionResult,
siteSpec: siteSpecResult,
globals: globalsResult,
taskFactorySpecs: taskFactoriesResult,
includedBuilds: includedBuildsResult
)
}

View File

@ -0,0 +1,24 @@
package com.jessebrault.ssg.buildscript
import com.jessebrault.ssg.util.Diagnostic
final class BuildUtil {
static Collection<Diagnostic> diagnoseIncludedBuilds(Collection<Build> allBuilds) {
allBuilds.inject([] as Collection<Diagnostic>) { allDiagnostics, build ->
allDiagnostics + build.includedBuilds.inject([] as Collection<Diagnostic>) { buildDiagnostics, includedBuildName ->
def includedBuild = allBuilds.find { it.name == includedBuildName }
if (includedBuild == null) {
buildDiagnostics + new Diagnostic(
"The includedBuild ${ includedBuildName } is not in the collection of allBuilds"
)
} else {
buildDiagnostics
}
}
}
}
private BuildUtil() {}
}

View File

@ -145,6 +145,21 @@ final class BuildDelegate {
}
}
Collection<String> getIncludedBuildsResult(
Collection<String> base,
boolean onConcatWithBaseEmpty,
Monoid<Collection<String>> includedBuildsMonoid
) {
def concatWithBase = this.delegate.includedBuildsConcatBase.isPresent()
? this.delegate.includedBuildsConcatBase.get()
: onConcatWithBaseEmpty
if (concatWithBase) {
includedBuildsMonoid.concat.apply(base, this.delegate.includedBuilds)
} else {
this.delegate.includedBuilds
}
}
}
private final Mutable<Function<Build, OutputDir>> outputDirFunction = Mutables.getEmpty()
@ -165,6 +180,9 @@ final class BuildDelegate {
private final Mutable<Boolean> taskFactoriesConcatBase = Mutables.getEmpty()
private final Mutable<Closure<?>> taskFactoriesClosure = Mutables.getEmpty()
private final Mutable<Boolean> includedBuildsConcatBase = Mutables.getEmpty()
private final Collection<String> includedBuilds = []
void setOutputDirFunction(Function<Build, OutputDir> outputDirFunction) {
this.outputDirFunction.set(outputDirFunction)
}
@ -284,4 +302,12 @@ final class BuildDelegate {
this.taskFactoriesClosure.set(taskFactoriesClosure)
}
void setConcatIncludedBuildsWithBase(boolean value) {
this.includedBuildsConcatBase.set(value)
}
void includeBuild(String buildName) {
this.includedBuilds << buildName
}
}

View File

@ -294,4 +294,31 @@ final class BuildDelegateTests {
assertEquals([], spec0.configurators)
}
private static Monoid<Collection<String>> getIncludedBuildsMonoid() {
Monoids.of([]) { c0, c1 -> c0 + c1 }
}
@Test
void includedBuildsNoBase() {
this.d.concatIncludedBuildsWithBase = false
this.d.includeBuild('included')
def r = this.results.getIncludedBuildsResult(
['notIncluded'], true, getIncludedBuildsMonoid()
)
assertEquals(1, r.size())
def includedBuild0 = r[0]
assertEquals('included', includedBuild0)
}
@Test
void includedBuildsWithBase() {
this.d.concatIncludedBuildsWithBase = true
def r = this.results.getIncludedBuildsResult(
['baseIncluded'], true, getIncludedBuildsMonoid()
)
assertEquals(1, r.size())
def includedBuild0 = r[0]
assertEquals('baseIncluded', includedBuild0)
}
}