From f3c6f1ef3c8c678635e2f8947a7ea552471318a5 Mon Sep 17 00:00:00 2001 From: JesseBrault0709 <62299747+JesseBrault0709@users.noreply.github.com> Date: Wed, 14 Jun 2023 21:35:14 +0200 Subject: [PATCH] Should be able to include builds. --- ...BuildScriptBasedStaticSiteGenerator.groovy | 71 +++++++++++++++---- .../jessebrault/ssg/buildscript/Build.groovy | 10 ++- .../ssg/buildscript/BuildSpecUtil.groovy | 21 ++++-- .../ssg/buildscript/BuildUtil.groovy | 24 +++++++ .../delegates/BuildDelegate.groovy | 26 +++++++ .../delegates/BuildDelegateTests.groovy | 27 +++++++ 6 files changed, 155 insertions(+), 24 deletions(-) create mode 100644 api/src/main/groovy/com/jessebrault/ssg/buildscript/BuildUtil.groovy diff --git a/api/src/main/groovy/com/jessebrault/ssg/BuildScriptBasedStaticSiteGenerator.groovy b/api/src/main/groovy/com/jessebrault/ssg/BuildScriptBasedStaticSiteGenerator.groovy index 5a85322..639185d 100644 --- a/api/src/main/groovy/com/jessebrault/ssg/BuildScriptBasedStaticSiteGenerator.groovy +++ b/api/src/main/groovy/com/jessebrault/ssg/BuildScriptBasedStaticSiteGenerator.groovy @@ -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 builds + final Collection 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 } } diff --git a/api/src/main/groovy/com/jessebrault/ssg/buildscript/Build.groovy b/api/src/main/groovy/com/jessebrault/ssg/buildscript/Build.groovy index cc7ac94..fbd8d2c 100644 --- a/api/src/main/groovy/com/jessebrault/ssg/buildscript/Build.groovy +++ b/api/src/main/groovy/com/jessebrault/ssg/buildscript/Build.groovy @@ -20,6 +20,7 @@ final class Build { OutputDirFunctions.DEFAULT, SiteSpec.getBlank(), [:], + [], [] ) } @@ -30,7 +31,8 @@ final class Build { args.outputDirFunction as Function ?: OutputDirFunctions.DEFAULT, args.siteSpec as SiteSpec ?: SiteSpec.getBlank(), args.globals as Map ?: [:], - args.taskFactorySpecs as Collection> ?: [] + args.taskFactorySpecs as Collection> ?: [], + args.includedBuilds as Collection ?: [] ) } @@ -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 globals final Collection> taskFactorySpecs + final Collection 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 })" } } diff --git a/api/src/main/groovy/com/jessebrault/ssg/buildscript/BuildSpecUtil.groovy b/api/src/main/groovy/com/jessebrault/ssg/buildscript/BuildSpecUtil.groovy index a246e5f..3a0d07c 100644 --- a/api/src/main/groovy/com/jessebrault/ssg/buildscript/BuildSpecUtil.groovy +++ b/api/src/main/groovy/com/jessebrault/ssg/buildscript/BuildSpecUtil.groovy @@ -25,6 +25,10 @@ final class BuildSpecUtil { m0 + m1 } + private static final Monoid> includedBuildsMonoid = Monoids.of([]) { c0, c1 -> + c0 + c1 + } + private static final Monoid>> 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 ) } diff --git a/api/src/main/groovy/com/jessebrault/ssg/buildscript/BuildUtil.groovy b/api/src/main/groovy/com/jessebrault/ssg/buildscript/BuildUtil.groovy new file mode 100644 index 0000000..ea026cd --- /dev/null +++ b/api/src/main/groovy/com/jessebrault/ssg/buildscript/BuildUtil.groovy @@ -0,0 +1,24 @@ +package com.jessebrault.ssg.buildscript + +import com.jessebrault.ssg.util.Diagnostic + +final class BuildUtil { + + static Collection diagnoseIncludedBuilds(Collection allBuilds) { + allBuilds.inject([] as Collection) { allDiagnostics, build -> + allDiagnostics + build.includedBuilds.inject([] as Collection) { 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() {} + +} diff --git a/api/src/main/groovy/com/jessebrault/ssg/buildscript/delegates/BuildDelegate.groovy b/api/src/main/groovy/com/jessebrault/ssg/buildscript/delegates/BuildDelegate.groovy index ee9a850..69655e0 100644 --- a/api/src/main/groovy/com/jessebrault/ssg/buildscript/delegates/BuildDelegate.groovy +++ b/api/src/main/groovy/com/jessebrault/ssg/buildscript/delegates/BuildDelegate.groovy @@ -145,6 +145,21 @@ final class BuildDelegate { } } + Collection getIncludedBuildsResult( + Collection base, + boolean onConcatWithBaseEmpty, + Monoid> 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> outputDirFunction = Mutables.getEmpty() @@ -165,6 +180,9 @@ final class BuildDelegate { private final Mutable taskFactoriesConcatBase = Mutables.getEmpty() private final Mutable> taskFactoriesClosure = Mutables.getEmpty() + private final Mutable includedBuildsConcatBase = Mutables.getEmpty() + private final Collection includedBuilds = [] + void setOutputDirFunction(Function 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 + } + } diff --git a/api/src/test/groovy/com/jessebrault/ssg/buildscript/delegates/BuildDelegateTests.groovy b/api/src/test/groovy/com/jessebrault/ssg/buildscript/delegates/BuildDelegateTests.groovy index d3e9e63..7612fe2 100644 --- a/api/src/test/groovy/com/jessebrault/ssg/buildscript/delegates/BuildDelegateTests.groovy +++ b/api/src/test/groovy/com/jessebrault/ssg/buildscript/delegates/BuildDelegateTests.groovy @@ -294,4 +294,31 @@ final class BuildDelegateTests { assertEquals([], spec0.configurators) } + private static Monoid> 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) + } + }