diff --git a/build-tools/geode-annotation-processor/build.gradle b/build-tools/geode-annotation-processor/build.gradle index 8dd0e9d4f3f3..1e985f9ab6e9 100644 --- a/build-tools/geode-annotation-processor/build.gradle +++ b/build-tools/geode-annotation-processor/build.gradle @@ -21,7 +21,6 @@ plugins { id 'java-gradle-plugin' id 'groovy-gradle-plugin' id 'maven-publish' - id 'com.gradle.plugin-publish' version '0.18.0' } repositories { diff --git a/build-tools/geode-build-tools/build.gradle b/build-tools/geode-build-tools/build.gradle index 1aca60b5fbad..aeaa924952c4 100644 --- a/build-tools/geode-build-tools/build.gradle +++ b/build-tools/geode-build-tools/build.gradle @@ -21,7 +21,6 @@ plugins { id 'java-gradle-plugin' id 'groovy-gradle-plugin' id 'maven-publish' - id 'com.gradle.plugin-publish' version '0.18.0' } repositories { @@ -48,4 +47,8 @@ gradlePlugin { id = 'org.apache.geode.gradle.geode-build-tools' implementationClass = 'org.apache.geode.gradle.plugins.BuildToolsPlugin' } + plugins.register('geode-facets') { + id = 'org.apache.geode.gradle.geode-facets' + implementationClass = 'org.apache.geode.gradle.plugins.FacetsPlugin' + } } diff --git a/build-tools/geode-build-tools/src/main/groovy/org/apache/geode/gradle/plugins/FacetsPlugin.groovy b/build-tools/geode-build-tools/src/main/groovy/org/apache/geode/gradle/plugins/FacetsPlugin.groovy new file mode 100644 index 000000000000..5287f44e2bf1 --- /dev/null +++ b/build-tools/geode-build-tools/src/main/groovy/org/apache/geode/gradle/plugins/FacetsPlugin.groovy @@ -0,0 +1,172 @@ +/* + * 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 + * + * http://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.apache.geode.gradle.plugins + +import org.gradle.api.Plugin +import org.gradle.api.Project +import org.gradle.api.plugins.JavaBasePlugin +import org.gradle.api.tasks.SourceSet +import org.gradle.api.tasks.SourceSetContainer +import org.gradle.api.tasks.testing.Test +import org.gradle.plugins.ide.eclipse.EclipsePlugin +import org.gradle.plugins.ide.eclipse.model.EclipseModel +import org.gradle.plugins.ide.idea.IdeaPlugin +import org.gradle.plugins.ide.idea.model.IdeaModel + +/** + * Adds a {@code facets} block that declares additional source sets, each extending a parent + * source set (by default {@code main}). A facet whose name contains {@code Test} also gets a + * {@link Test} task that runs its tests. + * + *
+ * facets {
+ *   integrationTest {
+ *     includeInCheckLifecycle = false
+ *   }
+ * }
+ * 
+ */ +class FacetsPlugin implements Plugin { + + @Override + void apply(Project project) { + project.extensions.add('facets', new FacetsExtension(project)) + } +} + +class FacetsExtension { + private final Project project + + FacetsExtension(Project project) { + this.project = project + } + + /** + * Declares a facet named after the method, configured by the closure argument. + */ + def methodMissing(String name, Object args) { + Object[] argArray = args as Object[] + if (argArray.length != 1 || !(argArray[0] instanceof Closure)) { + throw new MissingMethodException(name, getClass(), argArray) + } + FacetDefinition facet = new FacetDefinition(name) + Closure configuration = (argArray[0] as Closure).clone() as Closure + configuration.resolveStrategy = Closure.DELEGATE_FIRST + configuration.delegate = facet + configuration.call(facet) + addFacet(facet) + return facet + } + + private void addFacet(FacetDefinition facet) { + project.plugins.withType(JavaBasePlugin) { + SourceSetContainer sourceSets = project.extensions.getByType(SourceSetContainer) + sourceSets.matching { it.name == facet.parentSourceSet }.all { SourceSet parent -> + SourceSet sourceSet = createSourceSet(sourceSets, parent, facet) + + [ + [parent.compileClasspathConfigurationName, sourceSet.compileClasspathConfigurationName], + [parent.runtimeClasspathConfigurationName, sourceSet.runtimeClasspathConfigurationName], + [parent.annotationProcessorConfigurationName, sourceSet.annotationProcessorConfigurationName] + ].each { String parentName, String childName -> + project.configurations.getByName(childName) + .extendsFrom(project.configurations.getByName(parentName)) + } + + project.tasks.named('build').configure { it.dependsOn(sourceSet.classesTaskName) } + + if (facet.isTestFacet()) { + def testTask = createTestTask(facet.testTaskName, sourceSet) + if (facet.includeInCheckLifecycle) { + project.tasks.named('check').configure { it.dependsOn(testTask) } + } + } + + configureIde(sourceSet, facet.isTestFacet()) + } + } + } + + /** + * Creates the facet's source set. Its classpaths also include the output of its parent and, + * for a parent other than {@code main}, the output of {@code main}, which the parent sees. + */ + private SourceSet createSourceSet(SourceSetContainer sourceSets, SourceSet parent, + FacetDefinition facet) { + SourceSet main = sourceSets.getByName(SourceSet.MAIN_SOURCE_SET_NAME) + List parentOutputs = parent == main ? [main.output] : [parent.output, main.output] + return sourceSets.create(facet.name) { SourceSet sourceSet -> + sourceSet.compileClasspath = project.objects.fileCollection() + .from([sourceSet.compileClasspath] + parentOutputs) + sourceSet.runtimeClasspath = project.objects.fileCollection() + .from([sourceSet.runtimeClasspath] + parentOutputs) + } + } + + private def createTestTask(String testTaskName, SourceSet sourceSet) { + return project.tasks.register(testTaskName, Test) { Test test -> + test.group = JavaBasePlugin.VERIFICATION_GROUP + test.description = "Runs the ${sourceSet.name} tests" + test.reports.html.outputLocation.set( + project.layout.buildDirectory.dir("reports/${sourceSet.name}")) + test.reports.junitXml.outputLocation.set( + project.layout.buildDirectory.dir("${sourceSet.name}-results")) + test.testClassesDirs = sourceSet.output.classesDirs + test.classpath = sourceSet.runtimeClasspath + test.mustRunAfter(project.tasks.named('test')) + } + } + + private void configureIde(SourceSet sourceSet, boolean isTest) { + def classpathConfigurations = [ + project.configurations.getByName(sourceSet.compileClasspathConfigurationName), + project.configurations.getByName(sourceSet.runtimeClasspathConfigurationName) + ] + project.plugins.withType(IdeaPlugin) { + def module = project.extensions.getByType(IdeaModel).module + if (isTest) { + module.testSources.from(sourceSet.allSource.srcDirs) + module.scopes.TEST.plus += classpathConfigurations + } else { + module.sourceDirs += sourceSet.allSource.srcDirs + module.scopes.COMPILE.plus += classpathConfigurations + } + } + project.plugins.withType(EclipsePlugin) { + project.extensions.getByType(EclipseModel).classpath.plusConfigurations += + classpathConfigurations + } + } +} + +class FacetDefinition { + final String name + String parentSourceSet = SourceSet.MAIN_SOURCE_SET_NAME + String testTaskName + boolean includeInCheckLifecycle = true + + FacetDefinition(String name) { + this.name = name + } + + String getTestTaskName() { + return testTaskName ?: name + } + + boolean isTestFacet() { + return name.contains('Test') + } +} diff --git a/build-tools/geode-build-tools/src/main/groovy/org/apache/geode/gradle/plugins/PasswordDialog.groovy b/build-tools/geode-build-tools/src/main/groovy/org/apache/geode/gradle/plugins/PasswordDialog.groovy index 67072d3e044f..c32136daad49 100644 --- a/build-tools/geode-build-tools/src/main/groovy/org/apache/geode/gradle/plugins/PasswordDialog.groovy +++ b/build-tools/geode-build-tools/src/main/groovy/org/apache/geode/gradle/plugins/PasswordDialog.groovy @@ -17,28 +17,36 @@ package org.apache.geode.gradle.plugins -import groovy.swing.SwingBuilder +import java.awt.Frame +import javax.swing.Box +import javax.swing.JButton +import javax.swing.JDialog +import javax.swing.JLabel +import javax.swing.JPasswordField +import javax.swing.SwingUtilities class PasswordDialog { static String askPassword(String prompt) { def password = '' - new SwingBuilder().edt { - dialog(modal: true, - title: 'Password', - alwaysOnTop: true, - locationRelativeTo: null, - pack: true, - show: true - ) { - vbox { - label(text: prompt) - input = passwordField() - button(defaultButton: true, text: 'OK', actionPerformed: { - password = input.password.toString() // Set pass variable to value of input field - dispose() // Close dialog - }) - } + SwingUtilities.invokeAndWait { + JDialog dialog = new JDialog((Frame) null, 'Password', true) + JPasswordField input = new JPasswordField() + JButton ok = new JButton('OK') + ok.addActionListener { + password = new String(input.password) // Set pass variable to value of input field + dialog.dispose() // Close dialog } + + Box box = Box.createVerticalBox() + box.add(new JLabel(prompt)) + box.add(input) + box.add(ok) + dialog.contentPane.add(box) + dialog.rootPane.defaultButton = ok + dialog.alwaysOnTop = true + dialog.pack() + dialog.locationRelativeTo = null + dialog.visible = true } return password } diff --git a/build-tools/geode-dependency-management/src/main/groovy/org/apache/geode/gradle/plugins/DependencyConstraints.groovy b/build-tools/geode-dependency-management/src/main/groovy/org/apache/geode/gradle/plugins/DependencyConstraints.groovy index bc25ed544e3a..7124b025ee70 100644 --- a/build-tools/geode-dependency-management/src/main/groovy/org/apache/geode/gradle/plugins/DependencyConstraints.groovy +++ b/build-tools/geode-dependency-management/src/main/groovy/org/apache/geode/gradle/plugins/DependencyConstraints.groovy @@ -94,6 +94,7 @@ class DependencyConstraints { // These versions are referenced in test.gradle, which is aggressively injected into all projects. deps.put("junit.version", "4.13.2") deps.put("junit-jupiter.version", "5.8.2") + deps.put("junit-platform.version", "1.8.2") deps.put("cglib.version", "3.3.0") // This old version is for geode-assembly:acceptanceTest for gradle-in-gradle tests. As noted there, do not let diff --git a/build-tools/geode-repeat-test/build.gradle b/build-tools/geode-repeat-test/build.gradle index c4028cb971aa..259eb66c4a85 100644 --- a/build-tools/geode-repeat-test/build.gradle +++ b/build-tools/geode-repeat-test/build.gradle @@ -21,7 +21,6 @@ plugins { id 'java-gradle-plugin' id 'groovy-gradle-plugin' id 'maven-publish' - id 'com.gradle.plugin-publish' version '0.18.0' } repositories { diff --git a/build-tools/geode-repeat-test/src/main/groovy/org/apache/geode/gradle/testing/repeat/RepeatTest.groovy b/build-tools/geode-repeat-test/src/main/groovy/org/apache/geode/gradle/testing/repeat/RepeatTest.groovy index a51ddedaea51..b9704923ce1a 100644 --- a/build-tools/geode-repeat-test/src/main/groovy/org/apache/geode/gradle/testing/repeat/RepeatTest.groovy +++ b/build-tools/geode-repeat-test/src/main/groovy/org/apache/geode/gradle/testing/repeat/RepeatTest.groovy @@ -16,7 +16,6 @@ package org.apache.geode.gradle.testing.repeat import org.gradle.StartParameter import org.gradle.api.file.FileTree -import org.gradle.api.internal.DocumentationRegistry import org.gradle.api.internal.tasks.testing.JvmTestExecutionSpec import org.gradle.api.internal.tasks.testing.TestExecuter import org.gradle.api.internal.tasks.testing.filter.DefaultTestFilter @@ -56,7 +55,6 @@ public abstract class RepeatTest extends Test { getServices().get(WorkerLeaseService.class), getServices().get(StartParameter.class).getMaxWorkerCount(), getServices().get(Clock.class), - getServices().get(DocumentationRegistry.class), (DefaultTestFilter) getFilter(), times) } diff --git a/build-tools/geode-repeat-test/src/main/java/org/apache/geode/gradle/testing/repeat/ExecutionTrackingTestClassProcessor.java b/build-tools/geode-repeat-test/src/main/java/org/apache/geode/gradle/testing/repeat/ExecutionTrackingTestDefinitionProcessor.java similarity index 68% rename from build-tools/geode-repeat-test/src/main/java/org/apache/geode/gradle/testing/repeat/ExecutionTrackingTestClassProcessor.java rename to build-tools/geode-repeat-test/src/main/java/org/apache/geode/gradle/testing/repeat/ExecutionTrackingTestDefinitionProcessor.java index a639b4e19795..90a4a832b0bc 100644 --- a/build-tools/geode-repeat-test/src/main/java/org/apache/geode/gradle/testing/repeat/ExecutionTrackingTestClassProcessor.java +++ b/build-tools/geode-repeat-test/src/main/java/org/apache/geode/gradle/testing/repeat/ExecutionTrackingTestDefinitionProcessor.java @@ -14,19 +14,20 @@ */ package org.apache.geode.gradle.testing.repeat; -import org.gradle.api.internal.tasks.testing.TestClassProcessor; -import org.gradle.api.internal.tasks.testing.TestClassRunInfo; +import org.gradle.api.internal.tasks.testing.TestDefinition; +import org.gradle.api.internal.tasks.testing.TestDefinitionProcessor; import org.gradle.api.internal.tasks.testing.TestResultProcessor; /** - * A test class processor that decorates its result processor to associate each test event with - * the test class execution that reported it. + * A test definition processor that decorates its result processor to associate each test event + * with the test class execution that reported it. */ -public class ExecutionTrackingTestClassProcessor implements TestClassProcessor { - private final TestClassProcessor processor; +public class ExecutionTrackingTestDefinitionProcessor + implements TestDefinitionProcessor { + private final TestDefinitionProcessor processor; private final int iterationCount; - public ExecutionTrackingTestClassProcessor(TestClassProcessor processor, + public ExecutionTrackingTestDefinitionProcessor(TestDefinitionProcessor processor, int iterationCount) { this.processor = processor; this.iterationCount = iterationCount; @@ -39,8 +40,8 @@ public void startProcessing(TestResultProcessor resultProcessor) { } @Override - public void processTestClass(TestClassRunInfo testClass) { - processor.processTestClass(testClass); + public void processTestDefinition(D testDefinition) { + processor.processTestDefinition(testDefinition); } @Override diff --git a/build-tools/geode-repeat-test/src/main/java/org/apache/geode/gradle/testing/repeat/ExecutionTrackingTestResultProcessor.java b/build-tools/geode-repeat-test/src/main/java/org/apache/geode/gradle/testing/repeat/ExecutionTrackingTestResultProcessor.java index 2e679087da2b..360c1af40f4e 100644 --- a/build-tools/geode-repeat-test/src/main/java/org/apache/geode/gradle/testing/repeat/ExecutionTrackingTestResultProcessor.java +++ b/build-tools/geode-repeat-test/src/main/java/org/apache/geode/gradle/testing/repeat/ExecutionTrackingTestResultProcessor.java @@ -24,8 +24,9 @@ import org.gradle.api.internal.tasks.testing.TestDescriptorInternal; import org.gradle.api.internal.tasks.testing.TestResultProcessor; import org.gradle.api.internal.tasks.testing.TestStartEvent; -import org.gradle.api.internal.tasks.testing.worker.WorkerTestClassProcessor; +import org.gradle.api.internal.tasks.testing.worker.WorkerTestDefinitionProcessor; import org.gradle.api.tasks.testing.TestFailure; +import org.gradle.api.tasks.testing.TestMetadataEvent; import org.gradle.api.tasks.testing.TestOutputEvent; /** @@ -73,6 +74,11 @@ public void failure(Object testId, TestFailure result) { processor.failure(testId, result); } + @Override + public void published(Object testId, TestMetadataEvent event) { + processor.published(testId, event); + } + private TestDescriptorInternal executionTrackingDescriptor(TestDescriptorInternal original) { if (original instanceof DefaultTestDescriptor) { return executionTrackingTestDescriptor(original); @@ -83,7 +89,7 @@ private TestDescriptorInternal executionTrackingDescriptor(TestDescriptorInterna } return executionTrackingClassDescriptor(original); } - if (!(original instanceof WorkerTestClassProcessor.WorkerTestSuiteDescriptor)) { + if (!(original instanceof WorkerTestDefinitionProcessor.WorkerTestSuiteDescriptor)) { warnUnrecognized(original); } else { workerName = original.getName(); diff --git a/build-tools/geode-repeat-test/src/main/java/org/apache/geode/gradle/testing/repeat/RepeatTestExecuter.java b/build-tools/geode-repeat-test/src/main/java/org/apache/geode/gradle/testing/repeat/RepeatTestExecuter.java index 65b3a15f095d..f2a9af97224d 100644 --- a/build-tools/geode-repeat-test/src/main/java/org/apache/geode/gradle/testing/repeat/RepeatTestExecuter.java +++ b/build-tools/geode-repeat-test/src/main/java/org/apache/geode/gradle/testing/repeat/RepeatTestExecuter.java @@ -14,31 +14,35 @@ */ package org.apache.geode.gradle.testing.repeat; +import java.io.File; import java.util.ArrayList; +import java.util.Set; import org.gradle.api.file.FileTree; -import org.gradle.api.internal.DocumentationRegistry; import org.gradle.api.internal.classpath.ModuleRegistry; import org.gradle.api.internal.tasks.testing.JvmTestExecutionSpec; -import org.gradle.api.internal.tasks.testing.TestClassProcessor; +import org.gradle.api.internal.tasks.testing.TestDefinition; +import org.gradle.api.internal.tasks.testing.TestDefinitionProcessor; import org.gradle.api.internal.tasks.testing.TestExecuter; import org.gradle.api.internal.tasks.testing.TestFramework; import org.gradle.api.internal.tasks.testing.TestResultProcessor; -import org.gradle.api.internal.tasks.testing.WorkerTestClassProcessorFactory; -import org.gradle.api.internal.tasks.testing.detection.DefaultTestClassScanner; +import org.gradle.api.internal.tasks.testing.WorkerTestDefinitionProcessorFactory; import org.gradle.api.internal.tasks.testing.detection.DefaultTestExecuter; +import org.gradle.api.internal.tasks.testing.detection.DefaultTestScanner; import org.gradle.api.internal.tasks.testing.detection.ForkedTestClasspathFactory; +import org.gradle.api.internal.tasks.testing.detection.TestDetector; import org.gradle.api.internal.tasks.testing.detection.TestFrameworkDetector; import org.gradle.api.internal.tasks.testing.filter.DefaultTestFilter; -import org.gradle.api.internal.tasks.testing.processors.MaxNParallelTestClassProcessor; -import org.gradle.api.internal.tasks.testing.processors.PatternMatchTestClassProcessor; -import org.gradle.api.internal.tasks.testing.processors.RestartEveryNTestClassProcessor; -import org.gradle.api.internal.tasks.testing.processors.RunPreviousFailedFirstTestClassProcessor; +import org.gradle.api.internal.tasks.testing.processors.MaxNParallelTestDefinitionProcessor; +import org.gradle.api.internal.tasks.testing.processors.PatternMatchTestDefinitionProcessor; +import org.gradle.api.internal.tasks.testing.processors.RestartEveryNTestDefinitionProcessor; +import org.gradle.api.internal.tasks.testing.processors.RunPreviousFailedFirstTestDefinitionProcessor; import org.gradle.api.internal.tasks.testing.processors.TestMainAction; import org.gradle.api.internal.tasks.testing.worker.ForkedTestClasspath; -import org.gradle.api.internal.tasks.testing.worker.ForkingTestClassProcessor; +import org.gradle.api.internal.tasks.testing.worker.ForkingTestDefinitionProcessor; import org.gradle.api.logging.Logger; import org.gradle.api.logging.Logging; +import org.gradle.internal.Cast; import org.gradle.internal.Factory; import org.gradle.internal.actor.ActorFactory; import org.gradle.internal.time.Clock; @@ -46,17 +50,17 @@ import org.gradle.process.internal.worker.WorkerProcessFactory; /** - * A copy of {@link DefaultTestExecuter} from Gradle v8.14.5, modified to process each test class + * A copy of {@link DefaultTestExecuter} from Gradle v9.7.1, modified to process each test class * as many times as it was submitted. This is required by our {@link RepeatTest} task, because: *
    *
  • Geode's {@code RepeatTest} task operates by submitting each test class for processing * multiple times.
  • *
  • Gradle's {@code DefaultTestExecuter} includes a - * {@link RunPreviousFailedFirstTestClassProcessor}, which de-duplicates the submitted test + * {@link RunPreviousFailedFirstTestDefinitionProcessor}, which de-duplicates the submitted test * classes, preventing the {@code RepeatTest} from repeating the tests.
  • *
*

- * This executer omits the {@code RunPreviousFailedFirstTestClassProcessor}, and so each test class + * This executer omits the {@code RunPreviousFailedFirstTestDefinitionProcessor}, and so each test class * is processed as many times as {@code RepeatTest} submits it. See the comment in {@link #execute}. *

* This executer also assigns an ID to each execution of a test class, and appends that ID onto the @@ -73,22 +77,19 @@ public class RepeatTestExecuter implements TestExecuter { private final WorkerLeaseService workerLeaseService; private final int maxWorkerCount; private final Clock clock; - private final DocumentationRegistry documentationRegistry; private final DefaultTestFilter testFilter; private final int iterationCount; - private TestClassProcessor processor; + private TestDefinitionProcessor processor; public RepeatTestExecuter(WorkerProcessFactory workerFactory, ActorFactory actorFactory, ModuleRegistry moduleRegistry, WorkerLeaseService workerLeaseService, int maxWorkerCount, - Clock clock, DocumentationRegistry documentationRegistry, DefaultTestFilter testFilter, - int iterationCount) { + Clock clock, DefaultTestFilter testFilter, int iterationCount) { this.workerFactory = workerFactory; this.actorFactory = actorFactory; this.testClasspathFactory = new ForkedTestClasspathFactory(moduleRegistry); this.workerLeaseService = workerLeaseService; this.maxWorkerCount = maxWorkerCount; this.clock = clock; - this.documentationRegistry = documentationRegistry; this.testFilter = testFilter; this.iterationCount = iterationCount; } @@ -97,41 +98,41 @@ public RepeatTestExecuter(WorkerProcessFactory workerFactory, ActorFactory actor public void execute(final JvmTestExecutionSpec testExecutionSpec, TestResultProcessor testResultProcessor) { final TestFramework testFramework = testExecutionSpec.getTestFramework(); - final WorkerTestClassProcessorFactory testInstanceFactory = testFramework.getProcessorFactory(); + final WorkerTestDefinitionProcessorFactory testInstanceFactory = + Cast.uncheckedNonnullCast(testFramework.getProcessorFactory()); final ForkedTestClasspath classpath = testClasspathFactory.create( - testExecutionSpec.getClasspath(), testExecutionSpec.getModulePath(), testFramework, - testExecutionSpec.getTestIsModule()); - final Factory forkingProcessorFactory = () -> { - TestClassProcessor forkingTestClassProcessor = - new ForkingTestClassProcessor(workerLeaseService, workerFactory, testInstanceFactory, - testExecutionSpec.getJavaForkOptions(), classpath, - testFramework.getWorkerConfigurationAction(), documentationRegistry); + testExecutionSpec.getClasspath(), testExecutionSpec.getModulePath()); + final Factory> forkingProcessorFactory = () -> { + TestDefinitionProcessor forkingTestDefinitionProcessor = + new ForkingTestDefinitionProcessor<>(workerLeaseService, workerFactory, + testInstanceFactory, testExecutionSpec.getJavaForkOptions(), classpath, + testFramework.getWorkerConfigurationAction()); // Wrap the forking processor to make it distinguish different executions of a test class - return new ExecutionTrackingTestClassProcessor(forkingTestClassProcessor, iterationCount); + return new ExecutionTrackingTestDefinitionProcessor<>(forkingTestDefinitionProcessor, + iterationCount); }; - final Factory - reforkingProcessorFactory = - () -> new RestartEveryNTestClassProcessor(forkingProcessorFactory, + final Factory> reforkingProcessorFactory = + () -> new RestartEveryNTestDefinitionProcessor<>(forkingProcessorFactory, testExecutionSpec.getForkEvery()); - // Create the chain of test class processors, omitting the - // RunPreviousFailedFirstTestClassProcessor that Gradle's DefaultTestExecuter creates. + // Create the chain of test definition processors, omitting the + // RunPreviousFailedFirstTestDefinitionProcessor that Gradle's DefaultTestExecuter creates. processor = - new PatternMatchTestClassProcessor(testFilter, - new MaxNParallelTestClassProcessor(getMaxParallelForks(testExecutionSpec), + new PatternMatchTestDefinitionProcessor<>(testFilter, + new MaxNParallelTestDefinitionProcessor<>(getMaxParallelForks(testExecutionSpec), reforkingProcessorFactory, actorFactory)); final FileTree testClassFiles = testExecutionSpec.getCandidateClassFiles(); + final Set testDefinitionDirs = testExecutionSpec.getCandidateTestDefinitionDirs(); - Runnable detector; - if (testExecutionSpec.isScanForTestClasses() && testFramework.getDetector() != null) { - TestFrameworkDetector testFrameworkDetector = testFramework.getDetector(); - testFrameworkDetector + TestFrameworkDetector frameworkDetector = + testExecutionSpec.isScanForTestClasses() ? testFramework.getDetector() : null; + if (frameworkDetector != null) { + frameworkDetector .setTestClasses(new ArrayList<>(testExecutionSpec.getTestClassesDirs().getFiles())); - testFrameworkDetector.setTestClasspath(classpath.getApplicationClasspath()); - detector = new DefaultTestClassScanner(testClassFiles, testFrameworkDetector, processor); - } else { - detector = new DefaultTestClassScanner(testClassFiles, null, processor); + frameworkDetector.setTestClasspath(classpath.getApplicationClasspath()); } + TestDetector detector = + new DefaultTestScanner(testClassFiles, testDefinitionDirs, frameworkDetector, processor); new TestMainAction(detector, processor, testResultProcessor, workerLeaseService, clock, testExecutionSpec.getPath(), diff --git a/build-tools/geode-testing-isolation/build.gradle b/build-tools/geode-testing-isolation/build.gradle index ad921325db47..ba0329696a5f 100644 --- a/build-tools/geode-testing-isolation/build.gradle +++ b/build-tools/geode-testing-isolation/build.gradle @@ -21,7 +21,6 @@ plugins { id 'java-gradle-plugin' id 'groovy-gradle-plugin' id 'maven-publish' - id 'com.gradle.plugin-publish' version '0.18.0' } group = 'org.apache.geode.gradle' diff --git a/build-tools/geode-testing-isolation/src/main/groovy/org/apache/geode/gradle/testing/Executers.groovy b/build-tools/geode-testing-isolation/src/main/groovy/org/apache/geode/gradle/testing/Executers.groovy index c7c59c806042..7e674899a8f9 100644 --- a/build-tools/geode-testing-isolation/src/main/groovy/org/apache/geode/gradle/testing/Executers.groovy +++ b/build-tools/geode-testing-isolation/src/main/groovy/org/apache/geode/gradle/testing/Executers.groovy @@ -18,7 +18,6 @@ package org.apache.geode.gradle.testing import org.apache.geode.gradle.testing.process.AdjustableProcessLauncher import org.gradle.StartParameter -import org.gradle.api.internal.DocumentationRegistry import org.gradle.api.internal.tasks.testing.JvmTestExecutionSpec import org.gradle.api.internal.tasks.testing.TestExecuter import org.gradle.api.internal.tasks.testing.detection.DefaultTestExecuter @@ -51,7 +50,6 @@ class Executers { services.get(WorkerLeaseService), services.get(StartParameter).getMaxWorkerCount(), services.get(Clock), - services.get(DocumentationRegistry), testTask.filter ) } diff --git a/build-tools/scripts/build.gradle b/build-tools/scripts/build.gradle index 36cf1b2abdd6..debc48186b37 100644 --- a/build-tools/scripts/build.gradle +++ b/build-tools/scripts/build.gradle @@ -27,7 +27,7 @@ repositories { dependencies { implementation('org.apache.maven:maven-core:3.8.1') implementation('org.apache.maven:maven-model:3.8.1') - implementation('org.nosphere.apache:creadur-rat-gradle:0.7.1') + implementation('org.nosphere.apache:creadur-rat-gradle:0.11.0') implementation('com.github.ben-manes:gradle-versions-plugin:0.42.0') implementation("org.sonarsource.scanner.gradle:sonarqube-gradle-plugin:3.3") implementation('me.champeau.gradle:japicmp-gradle-plugin:0.4.6') diff --git a/build-tools/scripts/src/main/groovy/check-pom.gradle b/build-tools/scripts/src/main/groovy/check-pom.gradle index 4bd00d900edb..38fd9fe46908 100644 --- a/build-tools/scripts/src/main/groovy/check-pom.gradle +++ b/build-tools/scripts/src/main/groovy/check-pom.gradle @@ -15,6 +15,7 @@ * limitations under the License. */ +import groovy.xml.XmlParser import java.nio.file.Paths def expectedPomFile = Paths.get(projectDir.toString(), 'src', 'test', 'resources', 'expected-pom.xml') diff --git a/build-tools/scripts/src/main/groovy/geode-java.gradle b/build-tools/scripts/src/main/groovy/geode-java.gradle index 3cdfbd441fc4..ae0b5bc7f814 100644 --- a/build-tools/scripts/src/main/groovy/geode-java.gradle +++ b/build-tools/scripts/src/main/groovy/geode-java.gradle @@ -100,9 +100,11 @@ gradle.taskGraph.whenReady({ graph -> projectDependencies.add(dependency) } } else { - project.configurations.runtimeClasspath.files(dependency).each { depJar -> - runtimeSet.add(depJar.name) - } + // The artifacts of the dependency and of everything it brings in transitively + project.configurations.runtimeClasspath.resolvedConfiguration.firstLevelModuleDependencies + .findAll { it.moduleGroup == dependency.group && it.moduleName == dependency.name } + .collectMany { it.allModuleArtifacts } + .each { artifact -> runtimeSet.add(artifact.file.name) } } } @@ -113,7 +115,7 @@ gradle.taskGraph.whenReady({ graph -> // within it's parent's project dependencies. def upstreamDeps = [] projectDependencies.clone().each { ProjectDependency projectDependency -> - Project geodeProject = projectDependency.getDependencyProject() + Project geodeProject = project.project(projectDependency.path) Map depMap = new HashMap() def runtimeConfigList = getConfigurationsFor(geodeProject, 'runtimeClasspath') @@ -166,7 +168,9 @@ gradle.taskGraph.whenReady({ graph -> } jar.metaInf { from("$rootDir/geode-assembly/src/main/dist/LICENSE") - if (jar.source.filter({ it.name.contains('NOTICE') }).empty) { + // The JMH jar bundles project jars that already carry a NOTICE, and its contents cannot be + // inspected before those jars are built. + if (jar.name != 'jmhJar' && jar.source.filter({ it.name.contains('NOTICE') }).empty) { from("$rootDir/NOTICE") } } diff --git a/build-tools/scripts/src/main/groovy/geode-pmd.gradle b/build-tools/scripts/src/main/groovy/geode-pmd.gradle index dd55223a8d8e..2c77fa0d61b8 100644 --- a/build-tools/scripts/src/main/groovy/geode-pmd.gradle +++ b/build-tools/scripts/src/main/groovy/geode-pmd.gradle @@ -20,6 +20,7 @@ plugins { } pmd { + toolVersion = '6.42.0' sourceSets = [] ruleSetFiles = files("${project.projectDir}/../static-analysis/pmd-rules/src/main/resources/geodepmd.xml") ruleSets = [] diff --git a/build-tools/scripts/src/main/groovy/geode-test.gradle b/build-tools/scripts/src/main/groovy/geode-test.gradle index d23396dcc0ed..872b62c25aea 100644 --- a/build-tools/scripts/src/main/groovy/geode-test.gradle +++ b/build-tools/scripts/src/main/groovy/geode-test.gradle @@ -17,7 +17,7 @@ plugins { - id 'nebula.facet' + id 'org.apache.geode.gradle.geode-facets' id 'org.apache.geode.gradle.geode-build-tools' } @@ -128,7 +128,8 @@ tasks.register('repeatUpgradeTest', RepeatTest) { tasks.register('repeatUnitTest', RepeatTest) { dependsOn { test.taskDependencies } - // default classpath works for this one. + classpath = project.sourceSets.test.runtimeClasspath + testClassesDirs = project.sourceSets.test.output.classesDirs } configure([test, integrationTest, distributedTest, performanceTest, acceptanceTest, uiTest, upgradeTest, @@ -137,6 +138,12 @@ configure([test, integrationTest, distributedTest, performanceTest, acceptanceTe useJUnitPlatform() } +// Tests run on the JUnit Platform, whose launcher must be on each test runtime classpath +sourceSets.matching { it.name.toLowerCase().contains('test') }.configureEach { sourceSet -> + dependencies.add(sourceSet.runtimeOnlyConfigurationName, + 'org.junit.platform:junit-platform-launcher:' + DependencyConstraints.get('junit-platform.version')) +} + configure([integrationTest, distributedTest, performanceTest, acceptanceTest, uiTest, upgradeTest]) { if (project.hasProperty('excludeTest')) { exclude project.getProperty('excludeTest').split(',') diff --git a/build-tools/scripts/src/main/groovy/jmh.gradle b/build-tools/scripts/src/main/groovy/jmh.gradle index df16323e147d..2dd8d63d5412 100644 --- a/build-tools/scripts/src/main/groovy/jmh.gradle +++ b/build-tools/scripts/src/main/groovy/jmh.gradle @@ -16,8 +16,8 @@ */ plugins { - id 'me.champeau.gradle.jmh' - id 'nebula.facet' + id 'me.champeau.jmh' + id 'org.apache.geode.gradle.geode-facets' } configurations { @@ -33,22 +33,24 @@ dependencies { } jmh { - zip64 = true - duplicateClassesStrategy = 'exclude' - jvmArgs += ["-javaagent:${project.relativePath(configurations.javaagent.singleFile)}"] + // The JMH generator version this build has used; jmh-core is constrained separately. + jmhVersion = '1.25' + jvmArgs.add("-javaagent:${project.relativePath(configurations.javaagent.singleFile)}".toString()) - include = project.hasProperty('jmh.include') ? project.property('jmh.include').tokenize() : ['.*'] + includes = project.hasProperty('jmh.include') ? project.property('jmh.include').tokenize() : ['.*'] profilers = project.hasProperty('jmh.profilers') ? project.property('jmh.profilers').tokenize() : [] threads = project.hasProperty('jmh.threads') ? project.property('jmh.threads') as Integer : null warmupIterations = project.hasProperty('jmh.warmupIterations') ? project.property('jmh.warmupIterations') as Integer : null iterations = project.hasProperty('jmh.iterations') ? project.property('jmh.iterations') as Integer : null - timeOnIteration = project.hasProperty('jmh.timeOnIteration') ? project.property('jmh.timeOnIteration') as Integer : null + timeOnIteration = project.hasProperty('jmh.timeOnIteration') ? project.property('jmh.timeOnIteration') as String : null fork = project.hasProperty('jmh.fork') ? project.property('jmh.fork') as Integer : null jvm = project.hasProperty('jmh.jvm') ? project.property('jmh.jvm') as String : null - jvmArgs += project.hasProperty('jmh.jvmArgs') ? project.property('jmh.jvmArgs').tokenize() : [] + jvmArgs.addAll(project.hasProperty('jmh.jvmArgs') ? project.property('jmh.jvmArgs').tokenize() : []) } jmhJar { + zip64 = true + duplicatesStrategy = DuplicatesStrategy.EXCLUDE exclude(['META-INF/*.SF']) exclude('META-INF/org/apache/logging/log4j/core/config/plugins/Log4j2Plugins.dat') exclude('*.jar') diff --git a/build-tools/scripts/src/main/groovy/resolve-dependencies.gradle b/build-tools/scripts/src/main/groovy/resolve-dependencies.gradle index c6f1c6914c70..a644af2c3e19 100644 --- a/build-tools/scripts/src/main/groovy/resolve-dependencies.gradle +++ b/build-tools/scripts/src/main/groovy/resolve-dependencies.gradle @@ -30,10 +30,10 @@ allprojects { } } -// The default and archives configurations are not meant to be resolved; the classpath +// The default, archives and signatures configurations are not meant to be resolved; the classpath // configurations resolved alongside them cover the same dependencies. void resolveConfiguration(configuration) { - if (configuration.canBeResolved && !(configuration.name in ['default', 'archives'])) { + if (configuration.canBeResolved && !(configuration.name in ['default', 'archives', 'signatures'])) { configuration.resolve() } } diff --git a/build.gradle b/build.gradle index e727f23f43cf..2869523ba0d5 100755 --- a/build.gradle +++ b/build.gradle @@ -17,7 +17,6 @@ plugins { id "wrapper" - id "nebula.facet" version "8.0.0" apply false id "base" id "idea" id "eclipse" @@ -25,11 +24,11 @@ plugins { id "com.github.ben-manes.versions" version "0.42.0" apply false id "nebula.lint" version "17.7.0" apply false id "com.palantir.docker" version "0.40.0" apply false - id "io.spring.dependency-management" version "1.0.11.RELEASE" apply false + id "io.spring.dependency-management" version "1.1.7" apply false id "org.ajoberstar.grgit" version "4.1.1" apply false - id "org.nosphere.apache.rat" version "0.7.1" apply false + id "org.nosphere.apache.rat" version "0.11.0" apply false id "org.sonarqube" version "3.3" apply false - id 'me.champeau.gradle.jmh' version '0.5.3' apply false + id 'me.champeau.jmh' version '0.7.3' apply false id "de.undercouch.download" version "5.0.1" apply false id 'org.apache.geode.gradle.geode-dependency-constraints' apply false id 'geode-publish-artifacts' apply false @@ -108,6 +107,9 @@ task combineReports(type: TestReport) { // Explicitly depend on them so results exist before combining dependsOn allTests + // Run after whichever test tasks execute, since their results are combined + mustRunAfter(subprojects.collect { it.tasks.withType(Test) }) + doLast { println "All test reports at ${rootProject.buildDir}/reports/combined" } diff --git a/extensions/geode-modules-assembly/build.gradle b/extensions/geode-modules-assembly/build.gradle index 214a4860f4a4..68057c6e07e6 100644 --- a/extensions/geode-modules-assembly/build.gradle +++ b/extensions/geode-modules-assembly/build.gradle @@ -136,6 +136,11 @@ def configureTcServer30Assembly = { } } +// Archives keep the file system permissions, such as those of the executable scripts +tasks.withType(AbstractArchiveTask).configureEach { + useFileSystemPermissions() +} + tasks.register('distTomcat', Zip) { archiveBaseName = moduleBaseName archiveClassifier = "Tomcat" diff --git a/geode-assembly/build.gradle b/geode-assembly/build.gradle index 89f0679d18a3..549ada2bb4e4 100755 --- a/geode-assembly/build.gradle +++ b/geode-assembly/build.gradle @@ -82,7 +82,7 @@ gradle.taskGraph.whenReady( { graph -> it.name.toLowerCase().contains("dist") }.each { archive -> archive.doLast { - ant.checksum file:"${archive.archivePath}", algorithm:"sha-256", format: 'MD5SUM', fileext: '.sha256' + ant.checksum file:"${archive.archiveFile.get().asFile}", algorithm:"sha-256", format: 'MD5SUM', fileext: '.sha256' } } }) @@ -361,21 +361,21 @@ tasks.register('defaultCacheConfig', JavaExec) { def getDependencyProjectsFor(String configurationName) { List rval = configurations[configurationName].allDependencies.findAll { - it.hasProperty('dependencyProject') && it.dependencyProject != null + it instanceof ProjectDependency }.collect { - it.dependencyProject + project(it.path) }.collect { def projs = [it] if ((it as Project).pluginManager.hasPlugin('java-library')) { (it as Project).configurations.api.dependencies.findAll { - it.hasProperty('dependencyProject') && it.dependencyProject != null + it instanceof ProjectDependency }.collect { - projs += it.dependencyProject + projs += project(it.path) } (it as Project).configurations.runtimeOnly.dependencies.findAll { - it.hasProperty('dependencyProject') && it.dependencyProject != null + it instanceof ProjectDependency }.collect { - projs += it.dependencyProject + projs += project(it.path) } } projs @@ -479,6 +479,11 @@ tasks.register('docs', Javadoc) { } } +// Archives keep the file system permissions, such as those of the executable scripts +tasks.withType(AbstractArchiveTask).configureEach { + useFileSystemPermissions() +} + distributions { src { distributionBaseName = 'apache-geode' @@ -514,6 +519,12 @@ distributions { exclude { FileTreeElement details -> details.directory && (details.name == "build" || details.name == "out") } + + // The old version project directories are created when the build is configured + exclude { FileTreeElement details -> + details.directory && details.relativePath.parent?.pathString == 'geode-old-versions' && + details.name ==~ /\d+\.\d+\.\d+.*/ + } } } } @@ -575,7 +586,7 @@ distributions { with copySpec { into('tools/Pulse') - from {project(':geode-pulse').configurations.archives.allArtifacts.files} + from(project(':geode-pulse').tasks.named('war')) } with copySpec { diff --git a/geode-assembly/src/acceptanceTest/java/org/apache/geode/management/internal/rest/GradleBuildWithGeodeCoreAcceptanceTest.java b/geode-assembly/src/acceptanceTest/java/org/apache/geode/management/internal/rest/GradleBuildWithGeodeCoreAcceptanceTest.java index be6a57358f69..c03b38a8fef4 100644 --- a/geode-assembly/src/acceptanceTest/java/org/apache/geode/management/internal/rest/GradleBuildWithGeodeCoreAcceptanceTest.java +++ b/geode-assembly/src/acceptanceTest/java/org/apache/geode/management/internal/rest/GradleBuildWithGeodeCoreAcceptanceTest.java @@ -66,7 +66,7 @@ public void testBasicGradleBuild() { copyDirectoryResource(projectDir, buildDir); GradleConnector connector = GradleConnector.newConnector(); - connector.useGradleVersion("8.14.5"); + connector.useGradleVersion("9.7.1"); connector.forProjectDirectory(buildDir); ProjectConnection connection = connector.connect(); diff --git a/geode-core/build.gradle b/geode-core/build.gradle index 453c32139306..cf5ab2967df3 100755 --- a/geode-core/build.gradle +++ b/geode-core/build.gradle @@ -33,10 +33,10 @@ sourceSets { idea { module { - testSourceDirs += project.tasks.generateIntegrationTestGrammarSource.outputs.files - testSourceDirs += project.tasks.generateDistributedTestGrammarSource.outputs.files - testSourceDirs += project.tasks.generatePerformanceTestGrammarSource.outputs.files - testSourceDirs += project.tasks.generateUpgradeTestGrammarSource.outputs.files + testSources.from(project.tasks.generateIntegrationTestGrammarSource.outputs.files) + testSources.from(project.tasks.generateDistributedTestGrammarSource.outputs.files) + testSources.from(project.tasks.generatePerformanceTestGrammarSource.outputs.files) + testSources.from(project.tasks.generateUpgradeTestGrammarSource.outputs.files) } } @@ -134,7 +134,7 @@ tasks.register('jcaJar', Jar) { archiveBaseName='geode-jca' archiveExtension='rar' metaInf { from 'src/jca/ra.xml' } - from raJar.archivePath + from raJar.archiveFile } configurations { @@ -366,7 +366,6 @@ dependencies { testImplementation('com.tngtech.archunit:archunit-junit4') testImplementation(project(path: ':geode-core', configuration: 'raOutput')) testImplementation('org.springframework:spring-web') - testImplementation(files("${System.getProperty('java.home')}/../lib/tools.jar")) testImplementation('org.junit-pioneer:junit-pioneer') testCompileOnly('org.jetbrains:annotations') diff --git a/geode-web-management/build.gradle b/geode-web-management/build.gradle index 9b1f39270d26..0675acb67248 100644 --- a/geode-web-management/build.gradle +++ b/geode-web-management/build.gradle @@ -18,7 +18,7 @@ plugins { id 'war' id 'geode-publish-war' id 'warnings' - id 'nebula.facet' + id 'org.apache.geode.gradle.geode-facets' } jar.enabled = false @@ -73,6 +73,8 @@ facets { commonTest { useJUnitPlatform() + // Holds shared test support classes rather than tests + failOnNoDiscoveredTests = false } sourceSets { diff --git a/gradle.properties b/gradle.properties index 50609e2325a3..1deab46c5c0d 100755 --- a/gradle.properties +++ b/gradle.properties @@ -47,7 +47,7 @@ buildId = 0 productName = Apache Geode productOrg = Apache Software Foundation (ASF) -minimumGradleVersion = 8.14.5 +minimumGradleVersion = 9.7.1 # Set this on the command line with -P or in ~/.gradle/gradle.properties # to change the buildDir location. Use an absolute path. buildRoot= diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 1b33c55baabb..eddabd2eef8d 100644 Binary files a/gradle/wrapper/gradle-wrapper.jar and b/gradle/wrapper/gradle-wrapper.jar differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 70fe02a53692..8c1573900222 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,7 +1,9 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.14.5-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-9.7.1-all.zip networkTimeout=10000 +retries=0 +retryBackOffMs=500 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew index 23d15a936707..249efbb032ce 100755 --- a/gradlew +++ b/gradlew @@ -1,7 +1,7 @@ #!/bin/sh # -# Copyright © 2015-2021 the original authors. +# Copyright © 2015 the original authors. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -20,7 +20,7 @@ ############################################################################## # -# Gradle start up script for POSIX generated by Gradle. +# gradlew start up script for POSIX generated by Gradle. # # Important for running: # @@ -29,7 +29,7 @@ # bash, then to run this script, type that shell name before the whole # command line, like: # -# ksh Gradle +# ksh gradlew # # Busybox and similar reduced shells will NOT work, because this script # requires all of these POSIX shell features: @@ -57,7 +57,7 @@ # Darwin, MinGW, and NonStop. # # (3) This script is generated from the Groovy template -# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# https://github.com/gradle/gradle/blob/3d91ce3b8caaf77ad09f381f43615b715b53f72c/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt # within the Gradle project. # # You can find Gradle at https://github.com/gradle/gradle/. @@ -114,7 +114,6 @@ case "$( uname )" in #( NONSTOP* ) nonstop=true ;; esac -CLASSPATH="\\\"\\\"" # Determine the Java command to use to start the JVM. @@ -172,7 +171,6 @@ fi # For Cygwin or MSYS, switch paths to Windows format before running java if "$cygwin" || "$msys" ; then APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) - CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) JAVACMD=$( cygpath --unix "$JAVACMD" ) @@ -212,7 +210,6 @@ DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' set -- \ "-Dorg.gradle.appname=$APP_BASE_NAME" \ - -classpath "$CLASSPATH" \ -jar "$APP_HOME/gradle/wrapper/gradle-wrapper.jar" \ "$@" diff --git a/gradlew.bat b/gradlew.bat index 5eed7ee84528..8508ef684d4e 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -19,12 +19,12 @@ @if "%DEBUG%"=="" @echo off @rem ########################################################################## @rem -@rem Gradle startup script for Windows +@rem gradlew startup script for Windows @rem @rem ########################################################################## -@rem Set local scope for the variables with windows NT shell -if "%OS%"=="Windows_NT" setlocal +@rem Set local scope for the variables, and ensure extensions are enabled +setlocal EnableExtensions set DIRNAME=%~dp0 if "%DIRNAME%"=="" set DIRNAME=. @@ -51,7 +51,7 @@ echo. 1>&2 echo Please set the JAVA_HOME variable in your environment to match the 1>&2 echo location of your Java installation. 1>&2 -goto fail +"%COMSPEC%" /c exit 1 :findJavaFromJavaHome set JAVA_HOME=%JAVA_HOME:"=% @@ -65,30 +65,18 @@ echo. 1>&2 echo Please set the JAVA_HOME variable in your environment to match the 1>&2 echo location of your Java installation. 1>&2 -goto fail +"%COMSPEC%" /c exit 1 :execute @rem Setup the command line -set CLASSPATH= -@rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %* +@rem Execute gradlew +@rem endlocal doesn't take effect until after the line is parsed and variables are expanded +@rem which allows us to clear the local environment before executing the java command +endlocal & "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %* & call :exitWithErrorLevel -:end -@rem End local scope for the variables with windows NT shell -if %ERRORLEVEL% equ 0 goto mainEnd - -:fail -rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of -rem the _cmd.exe /c_ return code! -set EXIT_CODE=%ERRORLEVEL% -if %EXIT_CODE% equ 0 set EXIT_CODE=1 -if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% -exit /b %EXIT_CODE% - -:mainEnd -if "%OS%"=="Windows_NT" endlocal - -:omega +:exitWithErrorLevel +@rem Use "%COMSPEC%" /c exit to allow operators to work properly in scripts +"%COMSPEC%" /c exit %ERRORLEVEL% diff --git a/settings.gradle b/settings.gradle index 7b38f7b10f7a..fe4c3d9bb65b 100644 --- a/settings.gradle +++ b/settings.gradle @@ -132,6 +132,8 @@ include 'geode-server-all' '1.13.8', '1.14.0', // Include for SSL protocol configuration changes in 1.14.0 '1.14.4'].each { + // These project directories are not tracked in git and are removed by clean, so create them here. + file('geode-old-versions/'.concat(it)).mkdirs() include 'geode-old-versions:'.concat(it) }