jdaugherty commented on code in PR #16718: URL: https://github.com/apache/grails-core/pull/16718#discussion_r4348494874
########## grails-gradle/plugins/src/main/groovy/org/grails/gradle/plugin/views/ViewCompileEnvironment.groovy: ########## @@ -0,0 +1,171 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.grails.gradle.plugin.views + +import java.util.concurrent.Callable + +import groovy.transform.CompileStatic + +import org.gradle.api.InvalidUserDataException +import org.gradle.api.Transformer +import org.gradle.api.provider.Provider +import org.gradle.api.provider.ProviderFactory + +import grails.util.Environment + +/** + * The Grails environment a build compiles its views for. + * + * <p>Pages, JSON views and markup views are compiled ahead of time by a forked compiler that reads + * the application's configuration for the environment it runs in, so what a view compiles to - the + * codecs a page carries, for one - depends on that environment. The compile tasks state the + * environment as an input and hand it to the compiler, rather than leaving the compiler to whatever + * it inherits. This is where the input's default comes from, and how the input is read.</p> + * + * @since 7.0.18 + */ +@CompileStatic +final class ViewCompileEnvironment { + + /** The JVM argument a build gave the compiler its environment by, before the task had an input for it. */ + private static final String STATED_ARGUMENT = "-D${Environment.KEY}" + + /** The environments Grails has configuration blocks of its own for, by whichever name it accepts. */ + private static final List<Environment> KNOWN = [Environment.DEVELOPMENT, Environment.PRODUCTION, Environment.TEST].asImmutable() + + private ViewCompileEnvironment() { + } + + /** + * The default for a compile task's {@code grailsEnvironment}: an environment the build gave the + * compiler itself, as a {@code -Dgrails.env} JVM argument among the fork options of + * {@code options}, which is how a build chose the environment before the task had an input for + * it, else {@link #ofBuild the one the build runs with}. + * + * @param providers the build's providers + * @param options the task's compile options, whose fork options may name the environment + * @return the name of the environment, never absent + */ + static Provider<String> defaultFor(ProviderFactory providers, ViewCompileOptions options) { + providers.provider({ -> statedIn(options.forkOptions.jvmArgs) } as Callable<String>) + .orElse(ofBuild(providers)) + } + + /** + * The environment the build runs with: the {@code grails.env} system property given to Gradle, + * else the {@code GRAILS_ENV} environment variable, and {@code production} where neither is set, + * as the archive the views are packaged into is built for production unless the build says + * otherwise. + * + * @param providers the build's providers, which read the property and the variable + * @return the name of the environment, never absent + */ + static Provider<String> ofBuild(ProviderFactory providers) { + resolve(providers.systemProperty(Environment.KEY), providers.environmentVariable(Environment.ENV_KEY)) + } + + /** + * The environment {@code stated} names, else the one {@code inherited} names, else + * {@code production}. Each is read as {@link #canonicalName} reads it, so a blank one counts as + * not set and leaves the choice to the next, as the application's own resolution does. + * + * @param stated the name the build was given, the {@code grails.env} system property + * @param inherited the name the build inherited, the {@code GRAILS_ENV} environment variable + * @return the name of the environment, never absent + */ + static Provider<String> resolve(Provider<String> stated, Provider<String> inherited) { + Transformer<String, String> canonical = { String name -> canonicalName(name) } as Transformer<String, String> + stated.map(canonical) Review Comment: Agreed, and reverted in 08f238a7b5: the fallback is `development` again, as the fork has always had it. The input, the forwarding of `grails.env` and the emptied destination are what fix the cache defect, and they stay. A production default for the packaged archive is a separate change for a minor or major branch. ########## grails-gradle/plugins/src/main/groovy/org/grails/gradle/plugin/views/ViewCompileEnvironment.groovy: ########## @@ -0,0 +1,171 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.grails.gradle.plugin.views + +import java.util.concurrent.Callable + +import groovy.transform.CompileStatic + +import org.gradle.api.InvalidUserDataException +import org.gradle.api.Transformer +import org.gradle.api.provider.Provider +import org.gradle.api.provider.ProviderFactory + +import grails.util.Environment + +/** + * The Grails environment a build compiles its views for. + * + * <p>Pages, JSON views and markup views are compiled ahead of time by a forked compiler that reads + * the application's configuration for the environment it runs in, so what a view compiles to - the + * codecs a page carries, for one - depends on that environment. The compile tasks state the + * environment as an input and hand it to the compiler, rather than leaving the compiler to whatever + * it inherits. This is where the input's default comes from, and how the input is read.</p> + * + * @since 7.0.18 + */ +@CompileStatic +final class ViewCompileEnvironment { + + /** The JVM argument a build gave the compiler its environment by, before the task had an input for it. */ + private static final String STATED_ARGUMENT = "-D${Environment.KEY}" + + /** The environments Grails has configuration blocks of its own for, by whichever name it accepts. */ + private static final List<Environment> KNOWN = [Environment.DEVELOPMENT, Environment.PRODUCTION, Environment.TEST].asImmutable() + + private ViewCompileEnvironment() { + } + + /** + * The default for a compile task's {@code grailsEnvironment}: an environment the build gave the + * compiler itself, as a {@code -Dgrails.env} JVM argument among the fork options of + * {@code options}, which is how a build chose the environment before the task had an input for + * it, else {@link #ofBuild the one the build runs with}. + * + * @param providers the build's providers + * @param options the task's compile options, whose fork options may name the environment + * @return the name of the environment, never absent + */ + static Provider<String> defaultFor(ProviderFactory providers, ViewCompileOptions options) { + providers.provider({ -> statedIn(options.forkOptions.jvmArgs) } as Callable<String>) + .orElse(ofBuild(providers)) + } + + /** + * The environment the build runs with: the {@code grails.env} system property given to Gradle, + * else the {@code GRAILS_ENV} environment variable, and {@code production} where neither is set, + * as the archive the views are packaged into is built for production unless the build says + * otherwise. + * + * @param providers the build's providers, which read the property and the variable + * @return the name of the environment, never absent + */ + static Provider<String> ofBuild(ProviderFactory providers) { + resolve(providers.systemProperty(Environment.KEY), providers.environmentVariable(Environment.ENV_KEY)) + } + + /** + * The environment {@code stated} names, else the one {@code inherited} names, else + * {@code production}. Each is read as {@link #canonicalName} reads it, so a blank one counts as + * not set and leaves the choice to the next, as the application's own resolution does. + * + * @param stated the name the build was given, the {@code grails.env} system property + * @param inherited the name the build inherited, the {@code GRAILS_ENV} environment variable + * @return the name of the environment, never absent + */ + static Provider<String> resolve(Provider<String> stated, Provider<String> inherited) { Review Comment: A blank falls through here because that is how Grails already reads these selectors: `Environment` treats a blank `grails.env` as unset and reads `GRAILS_ENV`, and a blank `GRAILS_ENV` as unset, so the fork before this change, and the application at runtime, both resolve a blank the same way the task now does. Making a blank fail would change that for the build but not for the application it builds, which is a behaviour change beyond this bugfix, so I'd rather keep the two in step here. If a blank should be an error, that belongs to both, and I'd suggest a separate ticket for it so the runtime resolution and the compile tasks change together. -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: [email protected] For queries about this service, please contact Infrastructure at: [email protected]
