This is an automated email from the ASF dual-hosted git repository.
dsmiley pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/solr.git
The following commit(s) were added to refs/heads/main by this push:
new f0b5291f9d2 SOLR-17473: Introduce build tools formatting (#2739)
f0b5291f9d2 is described below
commit f0b5291f9d228833dcf52b6f8b145e2709f982b6
Author: Christos Malliaridis <[email protected]>
AuthorDate: Sat Oct 5 05:17:38 2024 +0200
SOLR-17473: Introduce build tools formatting (#2739)
* Migrate buildSrc to a composite included build
Migrate buildSrc into a composite included build (build-infra).
Expose a plugin with buildinfra extension.
* Configure tidy to run on infra classes
* Run tidy
* Add missing annotations
---
{buildSrc => build-tools/build-infra}/build.gradle | 37 ++-
.../build-infra/settings.gradle | 16 +-
.../java/org/apache/lucene/gradle/Checksum.java | 13 +-
.../lucene/gradle/ErrorReportingTestListener.java | 288 ++++++++++++++++++
.../lucene/gradle/GradlePropertiesGenerator.java | 2 +-
.../org/apache/lucene/gradle/PrefixedWriter.java | 11 +-
.../org/apache/lucene/gradle/ProfileResults.java | 71 +++--
.../java/org/apache/lucene/gradle/SpillWriter.java | 7 +-
.../org/apache/lucene/gradle/StdOutTeeWriter.java | 94 ++++++
.../apache/lucene/gradle/WrapperDownloader.java | 56 ++--
.../lucene/gradle/buildinfra/BuildInfraPlugin.java | 60 ++++
.../missing-doclet}/build.gradle | 24 +-
.../missing-doclet}/settings.gradle | 0
.../apache/lucene/missingdoclet/MissingDoclet.java | 321 +++++++++++----------
{buildSrc => build-tools}/scriptDepVersions.gradle | 1 +
build.gradle | 18 +-
.../lucene/gradle/ErrorReportingTestListener.java | 275 ------------------
.../org/apache/lucene/gradle/StdOutTeeWriter.java | 93 ------
dev-tools/README.txt | 1 -
buildSrc/build.gradle => gradle/conventions.gradle | 31 +-
gradle/testing/defaults-tests.gradle | 3 +-
gradle/testing/failed-tests-at-end.gradle | 4 +-
gradle/testing/profiling.gradle | 4 +-
gradle/validation/check-environment.gradle | 1 +
gradle/validation/jar-checks.gradle | 4 +-
gradle/validation/owasp-dependency-check.gradle | 2 +-
gradle/validation/rat-sources.gradle | 6 +-
gradle/validation/spotless.gradle | 23 +-
gradlew | 4 +-
gradlew.bat | 4 +-
settings.gradle | 4 +-
solr/distribution/build.gradle | 5 +-
32 files changed, 804 insertions(+), 679 deletions(-)
diff --git a/buildSrc/build.gradle b/build-tools/build-infra/build.gradle
similarity index 57%
copy from buildSrc/build.gradle
copy to build-tools/build-infra/build.gradle
index 91f88741322..0d78cce49bf 100644
--- a/buildSrc/build.gradle
+++ b/build-tools/build-infra/build.gradle
@@ -15,20 +15,43 @@
* limitations under the License.
*/
+plugins {
+ id "java-gradle-plugin"
+ id 'com.diffplug.spotless' version '6.5.2' apply false
+}
+
repositories {
mavenCentral()
}
-ext {
- // Minimum Java version required to compile buildSrc.
- minJavaVersion = JavaVersion.VERSION_11
-}
+group = "org.apache"
// Make sure the build environment is consistent.
-apply from: file('../gradle/validation/check-environment.gradle')
+apply from: file('../../gradle/conventions.gradle')
+apply from: file('../../gradle/validation/check-environment.gradle')
+
+// Add spotless/ tidy.
+tasks.register("checkJdkInternalsExportedToGradle") {}
+apply from: file('../../gradle/validation/spotless.gradle')
+
+// Load common script dependencies.
+apply from: file("../scriptDepVersions.gradle")
-// Load common buildSrc and script deps.
-apply from: file("scriptDepVersions.gradle")
+java {
+ sourceCompatibility = scriptDepVersions['min-java-version']
+ targetCompatibility = scriptDepVersions['min-java-version']
+}
+
+gradlePlugin {
+ automatedPublishing = false
+
+ plugins {
+ buildInfra {
+ id = 'solr.build-infra'
+ implementationClass =
'org.apache.lucene.gradle.buildinfra.BuildInfraPlugin'
+ }
+ }
+}
dependencies {
implementation gradleApi()
diff --git a/dev-tools/solr-missing-doclet/build.gradle
b/build-tools/build-infra/settings.gradle
similarity index 68%
copy from dev-tools/solr-missing-doclet/build.gradle
copy to build-tools/build-infra/settings.gradle
index e85f0a037e4..350b781b7f4 100644
--- a/dev-tools/solr-missing-doclet/build.gradle
+++ b/build-tools/build-infra/settings.gradle
@@ -15,18 +15,4 @@
* limitations under the License.
*/
-plugins {
- id 'java-library'
-}
-
-version = "1.0.0-SNAPSHOT"
-group = "org.apache.solr.tools"
-description = 'Doclet-based javadoc validation'
-
-sourceCompatibility = JavaVersion.VERSION_11
-targetCompatibility = JavaVersion.VERSION_11
-
-tasks.withType(JavaCompile) {
- options.compilerArgs += ["--release", targetCompatibility.toString()]
- options.encoding = "UTF-8"
-}
+rootProject.name = 'build-infra'
diff --git a/buildSrc/src/main/java/org/apache/lucene/gradle/Checksum.java
b/build-tools/build-infra/src/main/java/org/apache/lucene/gradle/Checksum.java
similarity index 99%
rename from buildSrc/src/main/java/org/apache/lucene/gradle/Checksum.java
rename to
build-tools/build-infra/src/main/java/org/apache/lucene/gradle/Checksum.java
index 0dab9dc7f05..a1d5c09586f 100644
--- a/buildSrc/src/main/java/org/apache/lucene/gradle/Checksum.java
+++
b/build-tools/build-infra/src/main/java/org/apache/lucene/gradle/Checksum.java
@@ -27,6 +27,11 @@
package org.apache.lucene.gradle;
+import java.io.File;
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.util.Locale;
import org.apache.commons.codec.digest.DigestUtils;
import org.gradle.api.DefaultTask;
import org.gradle.api.GradleException;
@@ -39,16 +44,10 @@ import org.gradle.api.tasks.TaskAction;
import org.gradle.work.Incremental;
import org.gradle.work.InputChanges;
-import java.io.File;
-import java.io.IOException;
-import java.nio.charset.StandardCharsets;
-import java.nio.file.Files;
-import java.util.Locale;
-
public class Checksum extends DefaultTask {
private FileCollection files;
private File outputDir;
- private Algorithm algorithm;
+ private Algorithm algorithm = Checksum.Algorithm.SHA512;
public enum Algorithm {
MD5(new DigestUtils(DigestUtils.getMd5Digest())),
diff --git
a/build-tools/build-infra/src/main/java/org/apache/lucene/gradle/ErrorReportingTestListener.java
b/build-tools/build-infra/src/main/java/org/apache/lucene/gradle/ErrorReportingTestListener.java
new file mode 100644
index 00000000000..c1fb7b83983
--- /dev/null
+++
b/build-tools/build-infra/src/main/java/org/apache/lucene/gradle/ErrorReportingTestListener.java
@@ -0,0 +1,288 @@
+/*
+ * 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.lucene.gradle;
+
+import java.io.BufferedReader;
+import java.io.Closeable;
+import java.io.IOException;
+import java.io.UncheckedIOException;
+import java.io.Writer;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Objects;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.regex.Pattern;
+import org.gradle.api.internal.tasks.testing.logging.FullExceptionFormatter;
+import org.gradle.api.internal.tasks.testing.logging.TestExceptionFormatter;
+import org.gradle.api.logging.Logger;
+import org.gradle.api.logging.Logging;
+import org.gradle.api.tasks.testing.TestDescriptor;
+import org.gradle.api.tasks.testing.TestListener;
+import org.gradle.api.tasks.testing.TestOutputEvent;
+import org.gradle.api.tasks.testing.TestOutputListener;
+import org.gradle.api.tasks.testing.TestResult;
+import org.gradle.api.tasks.testing.logging.TestLogging;
+
+/**
+ * An error reporting listener that queues test output streams and displays
them on failure.
+ *
+ * <p>Heavily inspired by Elasticsearch's ErrorReportingTestListener (ASL 2.0
licensed).
+ */
+public class ErrorReportingTestListener implements TestOutputListener,
TestListener {
+ private static final Logger LOGGER =
Logging.getLogger(ErrorReportingTestListener.class);
+
+ private final TestExceptionFormatter formatter;
+ private final Map<TestKey, OutputHandler> outputHandlers = new
ConcurrentHashMap<>();
+ private final Path spillDir;
+ private final Path outputsDir;
+ private final boolean verboseMode;
+
+ public ErrorReportingTestListener(
+ TestLogging testLogging, Path spillDir, Path outputsDir, boolean
verboseMode) {
+ this.formatter = new FullExceptionFormatter(testLogging);
+ this.spillDir = spillDir;
+ this.outputsDir = outputsDir;
+ this.verboseMode = verboseMode;
+ }
+
+ @Override
+ public void onOutput(TestDescriptor testDescriptor, TestOutputEvent
outputEvent) {
+ handlerFor(testDescriptor).write(outputEvent);
+ }
+
+ @Override
+ public void beforeSuite(TestDescriptor suite) {
+ // noop.
+ }
+
+ @Override
+ public void beforeTest(TestDescriptor testDescriptor) {
+ // Noop.
+ }
+
+ @Override
+ public void afterSuite(final TestDescriptor suite, TestResult result) {
+ if (suite.getParent() == null || suite.getName().startsWith("Gradle")) {
+ return;
+ }
+
+ TestKey key = TestKey.of(suite);
+ try {
+ OutputHandler outputHandler = outputHandlers.get(key);
+ if (outputHandler != null) {
+ long length = outputHandler.length();
+ if (length > 1024 * 1024 * 10) {
+ LOGGER.warn(
+ String.format(
+ Locale.ROOT,
+ "WARNING: Test %s wrote %,d bytes of output.",
+ suite.getName(),
+ length));
+ }
+ }
+
+ boolean echoOutput = Objects.equals(result.getResultType(),
TestResult.ResultType.FAILURE);
+ boolean dumpOutput = echoOutput;
+
+ // If the test suite failed, report output.
+ if (dumpOutput || echoOutput) {
+ Files.createDirectories(outputsDir);
+ Path outputLog = outputsDir.resolve(getOutputLogName(suite));
+
+ // Save the output of a failing test to disk.
+ try (Writer w = Files.newBufferedWriter(outputLog,
StandardCharsets.UTF_8)) {
+ if (outputHandler != null) {
+ outputHandler.copyTo(w);
+ }
+ }
+
+ if (echoOutput && !verboseMode) {
+ synchronized (this) {
+ System.out.println("");
+ System.out.println(
+ suite.getClassName()
+ + " > test suite's output saved to "
+ + outputLog
+ + ", copied below:");
+ try (BufferedReader reader =
+ Files.newBufferedReader(outputLog, StandardCharsets.UTF_8)) {
+ char[] buf = new char[1024];
+ int len;
+ while ((len = reader.read(buf)) >= 0) {
+ System.out.print(new String(buf, 0, len));
+ }
+ System.out.println();
+ }
+ }
+ }
+ }
+ } catch (IOException e) {
+ throw new UncheckedIOException(e);
+ } finally {
+ OutputHandler handler = outputHandlers.remove(key);
+ if (handler != null) {
+ try {
+ handler.close();
+ } catch (IOException e) {
+ LOGGER.error("Failed to close output handler for: " + key, e);
+ }
+ }
+ }
+ }
+
+ private static Pattern SANITIZE = Pattern.compile("[^a-zA-Z .\\-_0-9]+");
+
+ public static String getOutputLogName(TestDescriptor suite) {
+ return SANITIZE.matcher("OUTPUT-" + suite.getName() +
".txt").replaceAll("_");
+ }
+
+ @Override
+ public void afterTest(TestDescriptor testDescriptor, TestResult result) {
+ // Include test failure exception stacktrace(s) in test output log.
+ if (result.getResultType() == TestResult.ResultType.FAILURE) {
+ if (result.getExceptions().size() > 0) {
+ String message = formatter.format(testDescriptor,
result.getExceptions());
+ handlerFor(testDescriptor).write(message);
+ }
+ }
+ }
+
+ private OutputHandler handlerFor(TestDescriptor descriptor) {
+ // Attach output of leaves (individual tests) to their parent.
+ if (!descriptor.isComposite()) {
+ descriptor = descriptor.getParent();
+ }
+ return outputHandlers.computeIfAbsent(TestKey.of(descriptor), (key) -> new
OutputHandler());
+ }
+
+ public static class TestKey {
+ private final String key;
+
+ private TestKey(String key) {
+ this.key = key;
+ }
+
+ public static TestKey of(TestDescriptor d) {
+ StringBuilder key = new StringBuilder();
+ key.append(d.getClassName());
+ key.append("::");
+ key.append(d.getName());
+ key.append("::");
+ key.append(d.getParent() == null ? "-" : d.getParent().toString());
+ return new TestKey(key.toString());
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ return o != null && o.getClass() == this.getClass() &&
Objects.equals(((TestKey) o).key, key);
+ }
+
+ @Override
+ public int hashCode() {
+ return key.hashCode();
+ }
+
+ @Override
+ public String toString() {
+ return key;
+ }
+ }
+
+ private class OutputHandler implements Closeable {
+ // Max single-line buffer before automatic wrap occurs.
+ private static final int MAX_LINE_WIDTH = 1024 * 4;
+
+ private final SpillWriter buffer;
+
+ // internal stream.
+ private final PrefixedWriter sint;
+ // stdout
+ private final PrefixedWriter sout;
+ // stderr
+ private final PrefixedWriter serr;
+
+ // last used stream (so that we can flush it properly and prefixes are not
screwed up).
+ private PrefixedWriter last;
+
+ public OutputHandler() {
+ buffer =
+ new SpillWriter(
+ () -> {
+ try {
+ return Files.createTempFile(spillDir, "spill-", ".tmp");
+ } catch (IOException e) {
+ throw new UncheckedIOException(e);
+ }
+ });
+
+ Writer sink = buffer;
+ if (verboseMode) {
+ sink = new StdOutTeeWriter(buffer);
+ }
+
+ sint = new PrefixedWriter(" > ", sink, MAX_LINE_WIDTH);
+ sout = new PrefixedWriter(" 1> ", sink, MAX_LINE_WIDTH);
+ serr = new PrefixedWriter(" 2> ", sink, MAX_LINE_WIDTH);
+ last = sint;
+ }
+
+ public void write(TestOutputEvent event) {
+ write(
+ (event.getDestination() == TestOutputEvent.Destination.StdOut ? sout
: serr),
+ event.getMessage());
+ }
+
+ public void write(String message) {
+ write(sint, message);
+ }
+
+ public long length() throws IOException {
+ return buffer.length();
+ }
+
+ private void write(PrefixedWriter out, String message) {
+ try {
+ if (out != last) {
+ last.completeLine();
+ last = out;
+ }
+ out.write(message);
+ } catch (IOException e) {
+ throw new UncheckedIOException("Unable to write to test output.", e);
+ }
+ }
+
+ public void copyTo(Writer out) throws IOException {
+ flush();
+ buffer.copyTo(out);
+ }
+
+ public void flush() throws IOException {
+ sout.completeLine();
+ serr.completeLine();
+ buffer.flush();
+ }
+
+ @Override
+ public void close() throws IOException {
+ buffer.close();
+ }
+ }
+}
diff --git
a/buildSrc/src/main/java/org/apache/lucene/gradle/GradlePropertiesGenerator.java
b/build-tools/build-infra/src/main/java/org/apache/lucene/gradle/GradlePropertiesGenerator.java
similarity index 96%
rename from
buildSrc/src/main/java/org/apache/lucene/gradle/GradlePropertiesGenerator.java
rename to
build-tools/build-infra/src/main/java/org/apache/lucene/gradle/GradlePropertiesGenerator.java
index db4f804f12e..5436afe70f8 100644
---
a/buildSrc/src/main/java/org/apache/lucene/gradle/GradlePropertiesGenerator.java
+++
b/build-tools/build-infra/src/main/java/org/apache/lucene/gradle/GradlePropertiesGenerator.java
@@ -67,6 +67,6 @@ public class GradlePropertiesGenerator {
fileContent = fileContent.replace(entry.getKey(),
String.valueOf(entry.getValue()));
}
Files.writeString(
- destination, fileContent, StandardCharsets.UTF_8,
StandardOpenOption.CREATE_NEW);
+ destination, fileContent, StandardCharsets.UTF_8,
StandardOpenOption.CREATE_NEW);
}
}
diff --git
a/buildSrc/src/main/java/org/apache/lucene/gradle/PrefixedWriter.java
b/build-tools/build-infra/src/main/java/org/apache/lucene/gradle/PrefixedWriter.java
similarity index 91%
rename from buildSrc/src/main/java/org/apache/lucene/gradle/PrefixedWriter.java
rename to
build-tools/build-infra/src/main/java/org/apache/lucene/gradle/PrefixedWriter.java
index 7281d496001..3dc663e8332 100644
--- a/buildSrc/src/main/java/org/apache/lucene/gradle/PrefixedWriter.java
+++
b/build-tools/build-infra/src/main/java/org/apache/lucene/gradle/PrefixedWriter.java
@@ -20,12 +20,13 @@ import java.io.IOException;
import java.io.Writer;
/**
- * Prefixes every new line with a given string, synchronizing multiple streams
to emit consistent lines.
+ * Prefixes every new line with a given string, synchronizing multiple streams
to emit consistent
+ * lines.
*/
public class PrefixedWriter extends Writer {
Writer sink;
- private final static char LF = '\n';
+ private static final char LF = '\n';
private final String prefix;
private final StringBuilder lineBuffer = new StringBuilder();
private final int maxLineLength;
@@ -45,7 +46,7 @@ public class PrefixedWriter extends Writer {
sink.write(LF);
lineBuffer.setLength(0);
- if (c != LF) {
+ if (c != LF) {
lineBuffer.append((char) c);
}
} else {
@@ -70,9 +71,7 @@ public class PrefixedWriter extends Writer {
throw new UnsupportedOperationException();
}
- /**
- * Complete the current line (emit LF if not at the start of the line
already).
- */
+ /** Complete the current line (emit LF if not at the start of the line
already). */
public void completeLine() throws IOException {
if (lineBuffer.length() > 0) {
write(LF);
diff --git
a/buildSrc/src/main/java/org/apache/lucene/gradle/ProfileResults.java
b/build-tools/build-infra/src/main/java/org/apache/lucene/gradle/ProfileResults.java
similarity index 79%
rename from buildSrc/src/main/java/org/apache/lucene/gradle/ProfileResults.java
rename to
build-tools/build-infra/src/main/java/org/apache/lucene/gradle/ProfileResults.java
index 60def1a89d1..15e0f11c56e 100644
--- a/buildSrc/src/main/java/org/apache/lucene/gradle/ProfileResults.java
+++
b/build-tools/build-infra/src/main/java/org/apache/lucene/gradle/ProfileResults.java
@@ -20,13 +20,12 @@ package org.apache.lucene.gradle;
import java.io.IOException;
import java.nio.file.Paths;
import java.util.AbstractMap.SimpleEntry;
-import java.util.Arrays;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
-
import jdk.jfr.consumer.RecordedClass;
import jdk.jfr.consumer.RecordedEvent;
import jdk.jfr.consumer.RecordedFrame;
@@ -36,15 +35,12 @@ import jdk.jfr.consumer.RecordedThread;
import jdk.jfr.consumer.RecordingFile;
/**
- * Processes an array of recording files (from tests), and prints a simple
histogram.
- * Inspired by the JFR example code.
- * Whole stacks are deduplicated (with the default stacksize being 1): you can
drill deeper
- * by adjusting the parameters.
+ * Processes an array of recording files (from tests), and prints a simple
histogram. Inspired by
+ * the JFR example code. Whole stacks are deduplicated (with the default
stacksize being 1): you can
+ * drill deeper by adjusting the parameters.
*/
public class ProfileResults {
- /**
- * Formats a frame to a formatted line. This is deduplicated on!
- */
+ /** Formats a frame to a formatted line. This is deduplicated on! */
static String frameToString(RecordedFrame frame, boolean lineNumbers) {
StringBuilder builder = new StringBuilder();
RecordedMethod method = frame.getMethod();
@@ -84,29 +80,32 @@ public class ProfileResults {
/**
* Driver method, for testing standalone.
+ *
* <pre>
* java -Dtests.profile.count=5
buildSrc/src/main/java/org/apache/lucene/gradle/ProfileResults.java \
* ./lucene/core/build/tmp/tests-cwd/somefile.jfr ...
* </pre>
*/
public static void main(String[] args) throws IOException {
- printReport(Arrays.asList(args),
- System.getProperty(MODE_KEY, MODE_DEFAULT),
- Integer.parseInt(System.getProperty(STACKSIZE_KEY,
STACKSIZE_DEFAULT)),
- Integer.parseInt(System.getProperty(COUNT_KEY, COUNT_DEFAULT)),
- Boolean.parseBoolean(System.getProperty(LINENUMBERS_KEY,
LINENUMBERS_DEFAULT)));
+ printReport(
+ Arrays.asList(args),
+ System.getProperty(MODE_KEY, MODE_DEFAULT),
+ Integer.parseInt(System.getProperty(STACKSIZE_KEY, STACKSIZE_DEFAULT)),
+ Integer.parseInt(System.getProperty(COUNT_KEY, COUNT_DEFAULT)),
+ Boolean.parseBoolean(System.getProperty(LINENUMBERS_KEY,
LINENUMBERS_DEFAULT)));
}
/** true if we care about this event */
static boolean isInteresting(String mode, RecordedEvent event) {
String name = event.getEventType().getName();
- switch(mode) {
+ switch (mode) {
case "cpu":
- return (name.equals("jdk.ExecutionSample") ||
name.equals("jdk.NativeMethodSample")) &&
- !isGradlePollThread(event.getThread("sampledThread"));
+ return (name.equals("jdk.ExecutionSample") ||
name.equals("jdk.NativeMethodSample"))
+ && !isGradlePollThread(event.getThread("sampledThread"));
case "heap":
- return (name.equals("jdk.ObjectAllocationInNewTLAB") ||
name.equals("jdk.ObjectAllocationOutsideTLAB")) &&
- !isGradlePollThread(event.getThread("eventThread"));
+ return (name.equals("jdk.ObjectAllocationInNewTLAB")
+ || name.equals("jdk.ObjectAllocationOutsideTLAB"))
+ && !isGradlePollThread(event.getThread("eventThread"));
default:
throw new UnsupportedOperationException(event.toString());
}
@@ -119,7 +118,7 @@ public class ProfileResults {
/** value we accumulate for this event */
static long getValue(RecordedEvent event) {
- switch(event.getEventType().getName()) {
+ switch (event.getEventType().getName()) {
case "jdk.ObjectAllocationInNewTLAB":
return event.getLong("tlabSize");
case "jdk.ObjectAllocationOutsideTLAB":
@@ -144,15 +143,17 @@ public class ProfileResults {
/** fixed width used for printing the different columns */
private static final int COLUMN_SIZE = 14;
+
private static final String COLUMN_PAD = "%-" + COLUMN_SIZE + "s";
+
private static String pad(String input) {
return String.format(Locale.ROOT, COLUMN_PAD, input);
}
- /**
- * Process all the JFR files passed in args and print a merged summary.
- */
- public static void printReport(List<String> files, String mode, int
stacksize, int count, boolean lineNumbers) throws IOException {
+ /** Process all the JFR files passed in args and print a merged summary. */
+ public static void printReport(
+ List<String> files, String mode, int stacksize, int count, boolean
lineNumbers)
+ throws IOException {
if (!"cpu".equals(mode) && !"heap".equals(mode)) {
throw new IllegalArgumentException("tests.profile.mode must be one of
(cpu,heap)");
}
@@ -178,14 +179,13 @@ public class ProfileResults {
StringBuilder stack = new StringBuilder();
for (int i = 0; i < Math.min(stacksize, trace.getFrames().size());
i++) {
if (stack.length() > 0) {
- stack.append("\n")
- .append(framePadding)
- .append(" at ");
+ stack.append("\n").append(framePadding).append(" at ");
}
stack.append(frameToString(trace.getFrames().get(i),
lineNumbers));
}
String line = stack.toString();
- SimpleEntry<String,Long> entry = histogram.computeIfAbsent(line, u
-> new SimpleEntry<>(line, 0L));
+ SimpleEntry<String, Long> entry =
+ histogram.computeIfAbsent(line, u -> new SimpleEntry<>(line,
0L));
long value = getValue(event);
entry.setValue(entry.getValue() + value);
totalEvents++;
@@ -195,12 +195,20 @@ public class ProfileResults {
}
}
// print summary from histogram
- System.out.printf(Locale.ROOT, "PROFILE SUMMARY from %d events (total:
%s)\n", totalEvents, formatValue(sumValues));
+ System.out.printf(
+ Locale.ROOT,
+ "PROFILE SUMMARY from %d events (total: %s)\n",
+ totalEvents,
+ formatValue(sumValues));
System.out.printf(Locale.ROOT, " tests.profile.mode=%s\n", mode);
System.out.printf(Locale.ROOT, " tests.profile.count=%d\n", count);
System.out.printf(Locale.ROOT, " tests.profile.stacksize=%d\n",
stacksize);
System.out.printf(Locale.ROOT, " tests.profile.linenumbers=%b\n",
lineNumbers);
- System.out.printf(Locale.ROOT, "%s%sSTACK\n", pad("PERCENT"),
pad(mode.toUpperCase(Locale.ROOT) + " SAMPLES"));
+ System.out.printf(
+ Locale.ROOT,
+ "%s%sSTACK\n",
+ pad("PERCENT"),
+ pad(mode.toUpperCase(Locale.ROOT) + " SAMPLES"));
List<SimpleEntry<String, Long>> entries = new
ArrayList<>(histogram.values());
entries.sort((u, v) -> v.getValue().compareTo(u.getValue()));
int seen = 0;
@@ -209,7 +217,8 @@ public class ProfileResults {
break;
}
String percent = String.format("%2.2f%%", 100 * (c.getValue() / (float)
sumValues));
- System.out.printf(Locale.ROOT, "%s%s%s\n", pad(percent),
pad(formatValue(c.getValue())), c.getKey());
+ System.out.printf(
+ Locale.ROOT, "%s%s%s\n", pad(percent),
pad(formatValue(c.getValue())), c.getKey());
}
}
}
diff --git a/buildSrc/src/main/java/org/apache/lucene/gradle/SpillWriter.java
b/build-tools/build-infra/src/main/java/org/apache/lucene/gradle/SpillWriter.java
similarity index 92%
rename from buildSrc/src/main/java/org/apache/lucene/gradle/SpillWriter.java
rename to
build-tools/build-infra/src/main/java/org/apache/lucene/gradle/SpillWriter.java
index f89977c2503..e9783d070b5 100644
--- a/buildSrc/src/main/java/org/apache/lucene/gradle/SpillWriter.java
+++
b/build-tools/build-infra/src/main/java/org/apache/lucene/gradle/SpillWriter.java
@@ -24,9 +24,10 @@ import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.function.Supplier;
+import org.jetbrains.annotations.NotNull;
public class SpillWriter extends Writer {
- private final static int MAX_BUFFERED = 2 * 1024;
+ private static final int MAX_BUFFERED = 2 * 1024;
private final StringWriter buffer = new StringWriter(MAX_BUFFERED);
private final Supplier<Path> spillPathSupplier;
@@ -38,7 +39,7 @@ public class SpillWriter extends Writer {
}
@Override
- public void write(char[] cbuf, int off, int len) throws IOException {
+ public void write(char @NotNull [] cbuf, int off, int len) throws
IOException {
getSink(len).write(cbuf, off, len);
}
@@ -58,7 +59,7 @@ public class SpillWriter extends Writer {
}
@Override
- public void write(String str, int off, int len) throws IOException {
+ public void write(@NotNull String str, int off, int len) throws IOException {
getSink(len).write(str, off, len);
}
diff --git
a/build-tools/build-infra/src/main/java/org/apache/lucene/gradle/StdOutTeeWriter.java
b/build-tools/build-infra/src/main/java/org/apache/lucene/gradle/StdOutTeeWriter.java
new file mode 100644
index 00000000000..71901259ea2
--- /dev/null
+++
b/build-tools/build-infra/src/main/java/org/apache/lucene/gradle/StdOutTeeWriter.java
@@ -0,0 +1,94 @@
+/*
+ * 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.lucene.gradle;
+
+import java.io.IOException;
+import java.io.PrintStream;
+import java.io.Writer;
+import org.jetbrains.annotations.NotNull;
+
+class StdOutTeeWriter extends Writer {
+ private final Writer delegate;
+ private final PrintStream out = System.out;
+
+ public StdOutTeeWriter(Writer delegate) {
+ this.delegate = delegate;
+ }
+
+ @Override
+ public void write(int c) throws IOException {
+ delegate.write(c);
+ out.write(c);
+ }
+
+ @Override
+ public void write(char @NotNull [] cbuf) throws IOException {
+ delegate.write(cbuf);
+ out.print(cbuf);
+ }
+
+ @Override
+ public void write(@NotNull String str) throws IOException {
+ delegate.write(str);
+ out.print(str);
+ }
+
+ @Override
+ public void write(@NotNull String str, int off, int len) throws IOException {
+ delegate.write(str, off, len);
+ out.append(str, off, len);
+ }
+
+ @Override
+ public Writer append(CharSequence csq) throws IOException {
+ delegate.append(csq);
+ out.append(csq);
+ return this;
+ }
+
+ @Override
+ public Writer append(CharSequence csq, int start, int end) throws
IOException {
+ delegate.append(csq, start, end);
+ out.append(csq, start, end);
+ return this;
+ }
+
+ @Override
+ public Writer append(char c) throws IOException {
+ delegate.append(c);
+ out.append(c);
+ return this;
+ }
+
+ @Override
+ public void write(char @NotNull [] cbuf, int off, int len) throws
IOException {
+ delegate.write(cbuf, off, len);
+ out.print(new String(cbuf, off, len));
+ }
+
+ @Override
+ public void flush() throws IOException {
+ delegate.flush();
+ out.flush();
+ }
+
+ @Override
+ public void close() throws IOException {
+ delegate.close();
+ // Don't close the actual output.
+ }
+}
diff --git
a/buildSrc/src/main/java/org/apache/lucene/gradle/WrapperDownloader.java
b/build-tools/build-infra/src/main/java/org/apache/lucene/gradle/WrapperDownloader.java
similarity index 78%
rename from
buildSrc/src/main/java/org/apache/lucene/gradle/WrapperDownloader.java
rename to
build-tools/build-infra/src/main/java/org/apache/lucene/gradle/WrapperDownloader.java
index e6930af7c74..f7e07eb164a 100644
--- a/buildSrc/src/main/java/org/apache/lucene/gradle/WrapperDownloader.java
+++
b/build-tools/build-infra/src/main/java/org/apache/lucene/gradle/WrapperDownloader.java
@@ -16,32 +16,26 @@
*/
package org.apache.lucene.gradle;
+import static java.nio.file.StandardCopyOption.REPLACE_EXISTING;
+
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
-import java.net.URLConnection;
-import java.nio.channels.Channels;
-import java.nio.channels.FileChannel;
-import java.nio.channels.ReadableByteChannel;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
-import java.util.EnumSet;
import java.util.Locale;
import java.util.concurrent.TimeUnit;
-import static java.nio.file.StandardCopyOption.REPLACE_EXISTING;
-import static java.nio.file.StandardOpenOption.APPEND;
-
/**
* Standalone class that can be used to download a gradle-wrapper.jar
- * <p>
- * Has no dependencies outside of standard java libraries
+ *
+ * <p>Has no dependencies outside of standard java libraries
*/
public class WrapperDownloader {
public static void main(String[] args) {
@@ -62,18 +56,21 @@ public class WrapperDownloader {
public static void checkVersion() {
int major = Runtime.getRuntime().version().feature();
if (major < 11 || major > 21) {
- throw new IllegalStateException("java version must be between 11 and 21,
your version: " + major);
+ throw new IllegalStateException(
+ "java version must be between 11 and 21, your version: " + major);
}
}
public void run(Path destination) throws IOException,
NoSuchAlgorithmException {
- Path checksumPath =
destination.resolveSibling(destination.getFileName().toString() + ".sha256");
+ Path checksumPath =
+ destination.resolveSibling(destination.getFileName().toString() +
".sha256");
if (!Files.exists(checksumPath)) {
throw new IOException("Checksum file not found: " + checksumPath);
}
String expectedChecksum = Files.readString(checksumPath,
StandardCharsets.UTF_8).trim();
- Path versionPath =
destination.resolveSibling(destination.getFileName().toString() + ".version");
+ Path versionPath =
+ destination.resolveSibling(destination.getFileName().toString() +
".version");
if (!Files.exists(versionPath)) {
throw new IOException("Wrapper version file not found: " + versionPath);
}
@@ -92,7 +89,11 @@ public class WrapperDownloader {
}
}
- URL url = new URL("https://raw.githubusercontent.com/gradle/gradle/v" +
wrapperVersion + "/gradle/wrapper/gradle-wrapper.jar");
+ URL url =
+ new URL(
+ "https://raw.githubusercontent.com/gradle/gradle/v"
+ + wrapperVersion
+ + "/gradle/wrapper/gradle-wrapper.jar");
System.err.println("Downloading gradle-wrapper.jar from " + url);
// Zero-copy save the jar to a temp file
@@ -108,7 +109,8 @@ public class WrapperDownloader {
} catch (IOException e) {
if (retries-- > 0) {
// Retry after a short delay
- System.err.println("Error connecting to server: " + e + ", will
retry in " + retryDelay + " seconds.");
+ System.err.println(
+ "Error connecting to server: " + e + ", will retry in " +
retryDelay + " seconds.");
Thread.sleep(TimeUnit.SECONDS.toMillis(retryDelay));
continue;
}
@@ -120,7 +122,12 @@ public class WrapperDownloader {
case HttpURLConnection.HTTP_BAD_GATEWAY:
if (retries-- > 0) {
// Retry after a short delay.
- System.err.println("Server returned HTTP " +
connection.getResponseCode() + ", will retry in " + retryDelay + " seconds.");
+ System.err.println(
+ "Server returned HTTP "
+ + connection.getResponseCode()
+ + ", will retry in "
+ + retryDelay
+ + " seconds.");
Thread.sleep(TimeUnit.SECONDS.toMillis(retryDelay));
continue;
}
@@ -131,13 +138,15 @@ public class WrapperDownloader {
}
try (InputStream is = connection.getInputStream();
- OutputStream out = Files.newOutputStream(temp)){
+ OutputStream out = Files.newOutputStream(temp)) {
is.transferTo(out);
}
String checksum = checksum(digest, temp);
if (!checksum.equalsIgnoreCase(expectedChecksum)) {
- throw new IOException(String.format(Locale.ROOT,
+ throw new IOException(
+ String.format(
+ Locale.ROOT,
"Checksum mismatch on downloaded gradle-wrapper.jar (was: %s,
expected: %s).",
checksum,
expectedChecksum));
@@ -146,8 +155,12 @@ public class WrapperDownloader {
Files.move(temp, destination, REPLACE_EXISTING);
temp = null;
} catch (IOException | InterruptedException e) {
- throw new IOException("Could not download gradle-wrapper.jar (" +
- e.getClass().getSimpleName() + ": " + e.getMessage() + ").");
+ throw new IOException(
+ "Could not download gradle-wrapper.jar ("
+ + e.getClass().getSimpleName()
+ + ": "
+ + e.getMessage()
+ + ").");
} finally {
if (temp != null) {
Files.deleteIfExists(temp);
@@ -165,7 +178,8 @@ public class WrapperDownloader {
}
return sb.toString();
} catch (IOException e) {
- throw new IOException("Could not compute digest of file: " + path + " ("
+ e.getMessage() + ")");
+ throw new IOException(
+ "Could not compute digest of file: " + path + " (" + e.getMessage()
+ ")");
}
}
}
diff --git
a/build-tools/build-infra/src/main/java/org/apache/lucene/gradle/buildinfra/BuildInfraPlugin.java
b/build-tools/build-infra/src/main/java/org/apache/lucene/gradle/buildinfra/BuildInfraPlugin.java
new file mode 100644
index 00000000000..415922a1916
--- /dev/null
+++
b/build-tools/build-infra/src/main/java/org/apache/lucene/gradle/buildinfra/BuildInfraPlugin.java
@@ -0,0 +1,60 @@
+/*
+ * 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.lucene.gradle.buildinfra;
+
+import java.nio.file.Path;
+import org.apache.commons.codec.digest.DigestUtils;
+import org.apache.lucene.gradle.Checksum;
+import org.apache.lucene.gradle.ErrorReportingTestListener;
+import org.apache.lucene.gradle.ProfileResults;
+import org.gradle.api.Plugin;
+import org.gradle.api.Project;
+import org.gradle.api.tasks.testing.TestDescriptor;
+import org.gradle.api.tasks.testing.logging.TestLogging;
+
+public class BuildInfraPlugin implements Plugin<Project> {
+ @Override
+ public void apply(Project project) {
+ project.getExtensions().create(BuildInfraExtension.NAME,
BuildInfraExtension.class);
+ }
+
+ public static class BuildInfraExtension {
+ public static final String NAME = "buildinfra";
+
+ public ErrorReportingTestListener newErrorReportingTestListener(
+ TestLogging testLogging, Path spillDir, Path outputsDir, boolean
verboseMode) {
+ return new ErrorReportingTestListener(testLogging, spillDir, outputsDir,
verboseMode);
+ }
+
+ public DigestUtils sha1Digest() {
+ return new DigestUtils(DigestUtils.getSha1Digest());
+ }
+
+ public String getOutputLogName(TestDescriptor suite) {
+ return ErrorReportingTestListener.getOutputLogName(suite);
+ }
+
+ public Class<?> checksumClass() {
+ return Checksum.class;
+ }
+
+ public Class<?> profileResultsClass() {
+ return ProfileResults.class;
+ }
+ }
+}
diff --git a/dev-tools/solr-missing-doclet/build.gradle
b/build-tools/missing-doclet/build.gradle
similarity index 61%
rename from dev-tools/solr-missing-doclet/build.gradle
rename to build-tools/missing-doclet/build.gradle
index e85f0a037e4..2525f50d79b 100644
--- a/dev-tools/solr-missing-doclet/build.gradle
+++ b/build-tools/missing-doclet/build.gradle
@@ -17,16 +17,34 @@
plugins {
id 'java-library'
+ id 'com.diffplug.spotless' version '6.5.2' apply false
+}
+
+repositories {
+ mavenCentral()
}
version = "1.0.0-SNAPSHOT"
group = "org.apache.solr.tools"
description = 'Doclet-based javadoc validation'
-sourceCompatibility = JavaVersion.VERSION_11
-targetCompatibility = JavaVersion.VERSION_11
+// Make sure the build environment is consistent.
+apply from: file('../../gradle/conventions.gradle')
+apply from: file('../../gradle/validation/check-environment.gradle')
+
+// Add spotless/ tidy.
+tasks.register("checkJdkInternalsExportedToGradle") {}
+apply from: file('../../gradle/validation/spotless.gradle')
+
+// Load common script dependencies.
+apply from: file("../scriptDepVersions.gradle")
+
+java {
+ sourceCompatibility = scriptDepVersions['min-java-version']
+ targetCompatibility = scriptDepVersions['min-java-version']
+}
-tasks.withType(JavaCompile) {
+tasks.withType(JavaCompile).configureEach {
options.compilerArgs += ["--release", targetCompatibility.toString()]
options.encoding = "UTF-8"
}
diff --git a/dev-tools/solr-missing-doclet/settings.gradle
b/build-tools/missing-doclet/settings.gradle
similarity index 100%
rename from dev-tools/solr-missing-doclet/settings.gradle
rename to build-tools/missing-doclet/settings.gradle
diff --git
a/dev-tools/solr-missing-doclet/src/main/java/org/apache/lucene/missingdoclet/MissingDoclet.java
b/build-tools/missing-doclet/src/main/java/org/apache/lucene/missingdoclet/MissingDoclet.java
similarity index 61%
rename from
dev-tools/solr-missing-doclet/src/main/java/org/apache/lucene/missingdoclet/MissingDoclet.java
rename to
build-tools/missing-doclet/src/main/java/org/apache/lucene/missingdoclet/MissingDoclet.java
index 36c0e4fe4c8..44c9c411a9e 100644
---
a/dev-tools/solr-missing-doclet/src/main/java/org/apache/lucene/missingdoclet/MissingDoclet.java
+++
b/build-tools/missing-doclet/src/main/java/org/apache/lucene/missingdoclet/MissingDoclet.java
@@ -16,6 +16,9 @@
*/
package org.apache.lucene.missingdoclet;
+import com.sun.source.doctree.DocCommentTree;
+import com.sun.source.doctree.ParamTree;
+import com.sun.source.util.DocTrees;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
@@ -24,7 +27,6 @@ import java.util.Locale;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;
-
import javax.lang.model.element.Element;
import javax.lang.model.element.ElementKind;
import javax.lang.model.element.ExecutableElement;
@@ -35,24 +37,19 @@ import javax.lang.model.type.TypeKind;
import javax.lang.model.util.ElementFilter;
import javax.lang.model.util.Elements;
import javax.tools.Diagnostic;
-
-import com.sun.source.doctree.DocCommentTree;
-import com.sun.source.doctree.ParamTree;
-import com.sun.source.util.DocTrees;
-
import jdk.javadoc.doclet.Doclet;
import jdk.javadoc.doclet.DocletEnvironment;
import jdk.javadoc.doclet.Reporter;
import jdk.javadoc.doclet.StandardDoclet;
/**
- * Checks for missing javadocs, where missing also means "only whitespace" or
"license header".
- * Has option --missing-level (package, class, method, parameter) so that we
can improve over time.
- * Has option --missing-ignore to ignore individual elements (such as split
packages).
- * It isn't recursive, just ignores exactly the elements you tell it.
- * This should be removed when packaging is fixed to no longer be split
across JARs.
- * Has option --missing-method to apply "method" level to selected packages
(fix one at a time).
- * Matches package names exactly: so you'll need to list subpackages
separately.
+ * Checks for missing javadocs, where missing also means "only whitespace" or
"license header". Has
+ * option --missing-level (package, class, method, parameter) so that we can
improve over time. Has
+ * option --missing-ignore to ignore individual elements (such as split
packages). It isn't
+ * recursive, just ignores exactly the elements you tell it. This should be
removed when packaging
+ * is fixed to no longer be split across JARs. Has option --missing-method to
apply "method" level
+ * to selected packages (fix one at a time). Matches package names exactly: so
you'll need to list
+ * subpackages separately.
*/
public class MissingDoclet extends StandardDoclet {
// checks that modules and packages have documentation
@@ -70,121 +67,124 @@ public class MissingDoclet extends StandardDoclet {
Elements elementUtils;
Set<String> ignored = Collections.emptySet();
Set<String> methodPackages = Collections.emptySet();
-
+
@Override
public Set<Doclet.Option> getSupportedOptions() {
Set<Doclet.Option> options = new HashSet<>();
options.addAll(super.getSupportedOptions());
- options.add(new Doclet.Option() {
- @Override
- public int getArgumentCount() {
- return 1;
- }
+ options.add(
+ new Doclet.Option() {
+ @Override
+ public int getArgumentCount() {
+ return 1;
+ }
- @Override
- public String getDescription() {
- return "level to enforce for missing javadocs: [package, class,
method, parameter]";
- }
+ @Override
+ public String getDescription() {
+ return "level to enforce for missing javadocs: [package, class,
method, parameter]";
+ }
- @Override
- public Kind getKind() {
- return Option.Kind.STANDARD;
- }
+ @Override
+ public Kind getKind() {
+ return Option.Kind.STANDARD;
+ }
- @Override
- public List<String> getNames() {
- return Collections.singletonList("--missing-level");
- }
+ @Override
+ public List<String> getNames() {
+ return Collections.singletonList("--missing-level");
+ }
- @Override
- public String getParameters() {
- return "level";
- }
+ @Override
+ public String getParameters() {
+ return "level";
+ }
- @Override
- public boolean process(String option, List<String> arguments) {
- switch (arguments.get(0)) {
- case "package":
- level = PACKAGE;
- return true;
- case "class":
- level = CLASS;
- return true;
- case "method":
- level = METHOD;
- return true;
- case "parameter":
- level = PARAMETER;
- return true;
- default:
- return false;
- }
- }
- });
- options.add(new Doclet.Option() {
- @Override
- public int getArgumentCount() {
- return 1;
- }
+ @Override
+ public boolean process(String option, List<String> arguments) {
+ switch (arguments.get(0)) {
+ case "package":
+ level = PACKAGE;
+ return true;
+ case "class":
+ level = CLASS;
+ return true;
+ case "method":
+ level = METHOD;
+ return true;
+ case "parameter":
+ level = PARAMETER;
+ return true;
+ default:
+ return false;
+ }
+ }
+ });
+ options.add(
+ new Doclet.Option() {
+ @Override
+ public int getArgumentCount() {
+ return 1;
+ }
- @Override
- public String getDescription() {
- return "comma separated list of element names to ignore (e.g. as a
workaround for split packages)";
- }
+ @Override
+ public String getDescription() {
+ return "comma separated list of element names to ignore (e.g. as a
workaround for split packages)";
+ }
- @Override
- public Kind getKind() {
- return Option.Kind.STANDARD;
- }
+ @Override
+ public Kind getKind() {
+ return Option.Kind.STANDARD;
+ }
- @Override
- public List<String> getNames() {
- return Collections.singletonList("--missing-ignore");
- }
+ @Override
+ public List<String> getNames() {
+ return Collections.singletonList("--missing-ignore");
+ }
- @Override
- public String getParameters() {
- return "ignoredNames";
- }
+ @Override
+ public String getParameters() {
+ return "ignoredNames";
+ }
- @Override
- public boolean process(String option, List<String> arguments) {
- ignored = new HashSet<>(Arrays.asList(arguments.get(0).split(",")));
- return true;
- }
- });
- options.add(new Doclet.Option() {
- @Override
- public int getArgumentCount() {
- return 1;
- }
+ @Override
+ public boolean process(String option, List<String> arguments) {
+ ignored = new
HashSet<>(Arrays.asList(arguments.get(0).split(",")));
+ return true;
+ }
+ });
+ options.add(
+ new Doclet.Option() {
+ @Override
+ public int getArgumentCount() {
+ return 1;
+ }
- @Override
- public String getDescription() {
- return "comma separated list of packages to check at 'method' level";
- }
+ @Override
+ public String getDescription() {
+ return "comma separated list of packages to check at 'method'
level";
+ }
- @Override
- public Kind getKind() {
- return Option.Kind.STANDARD;
- }
+ @Override
+ public Kind getKind() {
+ return Option.Kind.STANDARD;
+ }
- @Override
- public List<String> getNames() {
- return Collections.singletonList("--missing-method");
- }
+ @Override
+ public List<String> getNames() {
+ return Collections.singletonList("--missing-method");
+ }
- @Override
- public String getParameters() {
- return "packages";
- }
+ @Override
+ public String getParameters() {
+ return "packages";
+ }
- @Override
- public boolean process(String option, List<String> arguments) {
- methodPackages = new
HashSet<>(Arrays.asList(arguments.get(0).split(",")));
- return true;
- }
- });
+ @Override
+ public boolean process(String option, List<String> arguments) {
+ methodPackages = new
HashSet<>(Arrays.asList(arguments.get(0).split(",")));
+ return true;
+ }
+ });
return options;
}
@@ -205,10 +205,8 @@ public class MissingDoclet extends StandardDoclet {
return super.run(docEnv);
}
-
- /**
- * Returns effective check level for this element
- */
+
+ /** Returns effective check level for this element */
private int level(Element element) {
String pkg =
elementUtils.getPackageOf(element).getQualifiedName().toString();
if (methodPackages.contains(pkg)) {
@@ -217,24 +215,24 @@ public class MissingDoclet extends StandardDoclet {
return level;
}
}
-
- /**
- * Check an individual element.
- * This checks packages and types from the doctrees.
- * It will recursively check methods/fields from encountered types when the
level is "method"
+
+ /**
+ * Check an individual element. This checks packages and types from the
doctrees. It will
+ * recursively check methods/fields from encountered types when the level is
"method"
*/
private void check(Element element) {
- switch(element.getKind()) {
+ switch (element.getKind()) {
case MODULE:
// don't check the unnamed module, it won't have javadocs
- if (!((ModuleElement)element).isUnnamed()) {
+ if (!((ModuleElement) element).isUnnamed()) {
checkComment(element);
}
break;
case PACKAGE:
checkComment(element);
break;
- // class-like elements, check them, then recursively check their
children (fields and methods)
+ // class-like elements, check them, then recursively check their
children (fields and
+ // methods)
case CLASS:
case INTERFACE:
case ENUM:
@@ -242,17 +240,18 @@ public class MissingDoclet extends StandardDoclet {
if (level(element) >= CLASS) {
checkComment(element);
for (var subElement : element.getEnclosedElements()) {
- // don't recurse into enclosed types, otherwise we'll double-check
since they are already in the included docTree
- if (subElement.getKind() == ElementKind.METHOD ||
- subElement.getKind() == ElementKind.CONSTRUCTOR ||
- subElement.getKind() == ElementKind.FIELD ||
- subElement.getKind() == ElementKind.ENUM_CONSTANT) {
+ // don't recurse into enclosed types, otherwise we'll double-check
since they are
+ // already in the included docTree
+ if (subElement.getKind() == ElementKind.METHOD
+ || subElement.getKind() == ElementKind.CONSTRUCTOR
+ || subElement.getKind() == ElementKind.FIELD
+ || subElement.getKind() == ElementKind.ENUM_CONSTANT) {
check(subElement);
}
}
}
break;
- // method-like elements, check them if we are configured to do so
+ // method-like elements, check them if we are configured to do so
case METHOD:
case CONSTRUCTOR:
case FIELD:
@@ -267,9 +266,9 @@ public class MissingDoclet extends StandardDoclet {
}
/**
- * Return true if the method is synthetic enum method (values/valueOf).
- * According to the doctree documentation, the "included" set never includes
synthetic elements.
- * UweSays: It should not happen but it happens!
+ * Return true if the method is synthetic enum method (values/valueOf).
According to the doctree
+ * documentation, the "included" set never includes synthetic elements.
UweSays: It should not
+ * happen but it happens!
*/
private boolean isSyntheticEnumMethod(Element element) {
String simpleName = element.getSimpleName().toString();
@@ -280,20 +279,23 @@ public class MissingDoclet extends StandardDoclet {
}
return false;
}
-
+
/**
- * Checks that an element doesn't have missing javadocs.
- * In addition to truly "missing", check that comments aren't solely
whitespace (generated by some IDEs),
- * that they aren't a license header masquerading as a javadoc comment.
+ * Checks that an element doesn't have missing javadocs. In addition to
truly "missing", check
+ * that comments aren't solely whitespace (generated by some IDEs), that
they aren't a license
+ * header masquerading as a javadoc comment.
*/
private void checkComment(Element element) {
// sanity check that the element is really "included", because we do some
recursion into types
if (!docEnv.isIncluded(element)) {
return;
}
- // check that this element isn't on our ignore list. This is only used as
a workaround for "split packages".
- // ignoring a package isn't recursive (on purpose), we still check all the
classes, etc. inside it.
- // we just need to cope with the fact package-info.java isn't there
because it is split across multiple jars.
+ // check that this element isn't on our ignore list. This is only used as
a workaround for
+ // "split packages".
+ // ignoring a package isn't recursive (on purpose), we still check all the
classes, etc. inside
+ // it.
+ // we just need to cope with the fact package-info.java isn't there
because it is split across
+ // multiple jars.
if (ignored.contains(element.toString())) {
return;
}
@@ -306,14 +308,17 @@ public class MissingDoclet extends StandardDoclet {
error(element, "javadocs are missing");
}
} else {
- var normalized = tree.getFirstSentence().get(0).toString()
- .replace('\u00A0', ' ')
- .trim()
- .toLowerCase(Locale.ROOT);
+ var normalized =
+ tree.getFirstSentence()
+ .get(0)
+ .toString()
+ .replace('\u00A0', ' ')
+ .trim()
+ .toLowerCase(Locale.ROOT);
if (normalized.isEmpty()) {
error(element, "blank javadoc comment");
- } else if (normalized.startsWith("licensed to the apache software
foundation") ||
- normalized.startsWith("copyright 2004 the apache software
foundation")) {
+ } else if (normalized.startsWith("licensed to the apache software
foundation")
+ || normalized.startsWith("copyright 2004 the apache software
foundation")) {
error(element, "comment is really a license");
}
}
@@ -323,13 +328,15 @@ public class MissingDoclet extends StandardDoclet {
}
private boolean hasInheritedJavadocs(Element element) {
- boolean hasOverrides = element.getAnnotationMirrors().stream()
- .anyMatch(ann ->
ann.getAnnotationType().toString().equals(Override.class.getName()));
+ boolean hasOverrides =
+ element.getAnnotationMirrors().stream()
+ .anyMatch(ann ->
ann.getAnnotationType().toString().equals(Override.class.getName()));
if (hasOverrides) {
// If an element has explicit @Overrides annotation, assume it does
// have inherited javadocs somewhere.
- reporter.print(Diagnostic.Kind.NOTE, element, "javadoc empty but
@Override declared, skipping.");
+ reporter.print(
+ Diagnostic.Kind.NOTE, element, "javadoc empty but @Override
declared, skipping.");
return true;
}
@@ -346,7 +353,10 @@ public class MissingDoclet extends StandardDoclet {
// We could check supMethod for non-empty javadoc here. Don't know
if this makes
// sense though as all methods will be verified in the end so it'd
fail on the
// top of the hierarchy (if empty) anyway.
- reporter.print(Diagnostic.Kind.NOTE, element, "javadoc empty but
method overrides another, skipping.");
+ reporter.print(
+ Diagnostic.Kind.NOTE,
+ element,
+ "javadoc empty but method overrides another, skipping.");
return true;
}
}
@@ -356,15 +366,14 @@ public class MissingDoclet extends StandardDoclet {
return false;
}
-
/* Find types from which methods in type may inherit javadoc, in the proper
order.*/
private Stream<Element> superTypeForInheritDoc(Element type) {
TypeElement clazz = (TypeElement) type;
- List<Element> interfaces = clazz.getInterfaces()
- .stream()
- .filter(tm -> tm.getKind() == TypeKind.DECLARED)
- .map(tm -> ((DeclaredType) tm).asElement())
- .collect(Collectors.toList());
+ List<Element> interfaces =
+ clazz.getInterfaces().stream()
+ .filter(tm -> tm.getKind() == TypeKind.DECLARED)
+ .map(tm -> ((DeclaredType) tm).asElement())
+ .collect(Collectors.toList());
Stream<Element> result = interfaces.stream();
result = Stream.concat(result,
interfaces.stream().flatMap(this::superTypeForInheritDoc));
@@ -386,13 +395,13 @@ public class MissingDoclet extends StandardDoclet {
if (tree != null) {
for (var tag : tree.getBlockTags()) {
if (tag instanceof ParamTree) {
- var name = ((ParamTree)tag).getName().getName().toString();
+ var name = ((ParamTree) tag).getName().getName().toString();
seenParameters.add(name);
}
}
}
// now compare the method's formal parameter list against it
- for (var param : ((ExecutableElement)element).getParameters()) {
+ for (var param : ((ExecutableElement) element).getParameters()) {
var name = param.getSimpleName().toString();
if (!seenParameters.contains(name)) {
error(element, "missing javadoc @param for parameter '" + name +
"'");
@@ -400,7 +409,7 @@ public class MissingDoclet extends StandardDoclet {
}
}
}
-
+
/** logs a new error for the particular element */
private void error(Element element, String message) {
var fullMessage = new StringBuilder();
diff --git a/buildSrc/scriptDepVersions.gradle
b/build-tools/scriptDepVersions.gradle
similarity index 97%
rename from buildSrc/scriptDepVersions.gradle
rename to build-tools/scriptDepVersions.gradle
index a1d2bc9467d..2a83896148e 100644
--- a/buildSrc/scriptDepVersions.gradle
+++ b/build-tools/scriptDepVersions.gradle
@@ -21,6 +21,7 @@
ext {
scriptDepVersions = [
+ "min-java-version": "11",
"apache-rat": "0.15",
"commons-codec": "1.16.0",
"ecj": "3.33.0",
diff --git a/build.gradle b/build.gradle
index 3b3c0e0999e..3cecb1aa0cd 100644
--- a/build.gradle
+++ b/build.gradle
@@ -20,6 +20,7 @@ import java.time.format.DateTimeFormatter
plugins {
id 'base'
+ id 'solr.build-infra'
id 'com.palantir.consistent-versions' version '2.16.0'
id 'org.owasp.dependencycheck' version '9.0.8'
id 'ca.cutterslade.analyze' version '1.10.0'
@@ -30,9 +31,11 @@ plugins {
id 'com.github.node-gradle.node' version '7.0.1' apply false
}
+apply from: file('build-tools/scriptDepVersions.gradle')
+
// Declare default Java versions for the entire project and for SolrJ
separately
-rootProject.ext.minJavaVersionDefault = JavaVersion.VERSION_11
-rootProject.ext.minJavaVersionSolrJ = JavaVersion.VERSION_11
+rootProject.ext.minJavaVersionDefault =
JavaVersion.toVersion(scriptDepVersions['min-java-version'])
+rootProject.ext.minJavaVersionSolrJ =
JavaVersion.toVersion(scriptDepVersions['min-java-version'])
apply from: file('gradle/globals.gradle')
@@ -108,14 +111,13 @@ ext {
}
}
-apply from: file('buildSrc/scriptDepVersions.gradle')
-
// Include smaller chunks configuring dedicated build areas.
// Some of these intersect or add additional functionality.
// The order of inclusion of these files shouldn't matter (but may
// if the build file is incorrectly written and evaluates something
// eagerly).
+apply from: file('gradle/conventions.gradle')
apply from: file('gradle/generation/local-settings.gradle')
// Ant-compatibility layer: apply folder layout early so that
@@ -162,6 +164,14 @@ apply from:
file('gradle/validation/solr.config-file-sanity.gradle')
apply from: file('gradle/validation/spotless.gradle')
+// Wire up included builds to some validation tasks.
+rootProject.tasks.named("tidy").configure {
+ dependsOn gradle.includedBuilds*.task(":tidy")
+}
+rootProject.tasks.named("clean").configure {
+ dependsOn gradle.includedBuilds*.task(":clean")
+}
+
// Source or data regeneration tasks
apply from: file('gradle/generation/regenerate.gradle')
apply from: file('gradle/generation/javacc.gradle')
diff --git
a/buildSrc/src/main/java/org/apache/lucene/gradle/ErrorReportingTestListener.java
b/buildSrc/src/main/java/org/apache/lucene/gradle/ErrorReportingTestListener.java
deleted file mode 100644
index 44cd09b33f4..00000000000
---
a/buildSrc/src/main/java/org/apache/lucene/gradle/ErrorReportingTestListener.java
+++ /dev/null
@@ -1,275 +0,0 @@
-/*
- * 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.lucene.gradle;
-
-import java.io.*;
-import java.nio.charset.StandardCharsets;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.util.Locale;
-import java.util.Map;
-import java.util.Objects;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.regex.Pattern;
-
-import org.gradle.api.internal.tasks.testing.logging.FullExceptionFormatter;
-import org.gradle.api.internal.tasks.testing.logging.TestExceptionFormatter;
-import org.gradle.api.logging.Logger;
-import org.gradle.api.logging.Logging;
-import org.gradle.api.tasks.testing.TestDescriptor;
-import org.gradle.api.tasks.testing.TestListener;
-import org.gradle.api.tasks.testing.TestOutputEvent;
-import org.gradle.api.tasks.testing.TestOutputListener;
-import org.gradle.api.tasks.testing.TestResult;
-import org.gradle.api.tasks.testing.logging.TestLogging;
-
-/**
- * An error reporting listener that queues test output streams and displays
them
- * on failure.
- * <p>
- * Heavily inspired by Elasticsearch's ErrorReportingTestListener (ASL 2.0
licensed).
- */
-public class ErrorReportingTestListener implements TestOutputListener,
TestListener {
- private static final Logger LOGGER =
Logging.getLogger(ErrorReportingTestListener.class);
-
- private final TestExceptionFormatter formatter;
- private final Map<TestKey, OutputHandler> outputHandlers = new
ConcurrentHashMap<>();
- private final Path spillDir;
- private final Path outputsDir;
- private final boolean verboseMode;
-
- public ErrorReportingTestListener(TestLogging testLogging, Path spillDir,
Path outputsDir, boolean verboseMode) {
- this.formatter = new FullExceptionFormatter(testLogging);
- this.spillDir = spillDir;
- this.outputsDir = outputsDir;
- this.verboseMode = verboseMode;
- }
-
- @Override
- public void onOutput(TestDescriptor testDescriptor, TestOutputEvent
outputEvent) {
- handlerFor(testDescriptor).write(outputEvent);
- }
-
- @Override
- public void beforeSuite(TestDescriptor suite) {
- // noop.
- }
-
- @Override
- public void beforeTest(TestDescriptor testDescriptor) {
- // Noop.
- }
-
- @Override
- public void afterSuite(final TestDescriptor suite, TestResult result) {
- if (suite.getParent() == null || suite.getName().startsWith("Gradle")) {
- return;
- }
-
- TestKey key = TestKey.of(suite);
- try {
- OutputHandler outputHandler = outputHandlers.get(key);
- if (outputHandler != null) {
- long length = outputHandler.length();
- if (length > 1024 * 1024 * 10) {
- LOGGER.warn(String.format(Locale.ROOT, "WARNING: Test %s wrote
%,d bytes of output.",
- suite.getName(),
- length));
- }
- }
-
- boolean echoOutput = Objects.equals(result.getResultType(),
TestResult.ResultType.FAILURE);
- boolean dumpOutput = echoOutput;
-
- // If the test suite failed, report output.
- if (dumpOutput || echoOutput) {
- Files.createDirectories(outputsDir);
- Path outputLog = outputsDir.resolve(getOutputLogName(suite));
-
- // Save the output of a failing test to disk.
- try (Writer w = Files.newBufferedWriter(outputLog,
StandardCharsets.UTF_8)) {
- if (outputHandler != null) {
- outputHandler.copyTo(w);
- }
- }
-
- if (echoOutput && !verboseMode) {
- synchronized (this) {
- System.out.println("");
- System.out.println(suite.getClassName() + " > test suite's
output saved to " + outputLog + ", copied below:");
- try (BufferedReader reader =
Files.newBufferedReader(outputLog, StandardCharsets.UTF_8)) {
- char[] buf = new char[1024];
- int len;
- while ((len = reader.read(buf)) >= 0) {
- System.out.print(new String(buf, 0, len));
- }
- System.out.println();
- }
- }
- }
- }
- } catch (IOException e) {
- throw new UncheckedIOException(e);
- } finally {
- OutputHandler handler = outputHandlers.remove(key);
- if (handler != null) {
- try {
- handler.close();
- } catch (IOException e) {
- LOGGER.error("Failed to close output handler for: " + key, e);
- }
- }
- }
- }
-
- private static Pattern SANITIZE = Pattern.compile("[^a-zA-Z .\\-_0-9]+");
-
- public static String getOutputLogName(TestDescriptor suite) {
- return SANITIZE.matcher("OUTPUT-" + suite.getName() +
".txt").replaceAll("_");
- }
-
- @Override
- public void afterTest(TestDescriptor testDescriptor, TestResult result) {
- // Include test failure exception stacktrace(s) in test output log.
- if (result.getResultType() == TestResult.ResultType.FAILURE) {
- if (result.getExceptions().size() > 0) {
- String message = formatter.format(testDescriptor,
result.getExceptions());
- handlerFor(testDescriptor).write(message);
- }
- }
- }
-
- private OutputHandler handlerFor(TestDescriptor descriptor) {
- // Attach output of leaves (individual tests) to their parent.
- if (!descriptor.isComposite()) {
- descriptor = descriptor.getParent();
- }
- return outputHandlers.computeIfAbsent(TestKey.of(descriptor), (key) ->
new OutputHandler());
- }
-
- public static class TestKey {
- private final String key;
-
- private TestKey(String key) {
- this.key = key;
- }
-
- public static TestKey of(TestDescriptor d) {
- StringBuilder key = new StringBuilder();
- key.append(d.getClassName());
- key.append("::");
- key.append(d.getName());
- key.append("::");
- key.append(d.getParent() == null ? "-" : d.getParent().toString());
- return new TestKey(key.toString());
- }
-
- @Override
- public boolean equals(Object o) {
- return o != null &&
- o.getClass() == this.getClass() &&
- Objects.equals(((TestKey) o).key, key);
- }
-
- @Override
- public int hashCode() {
- return key.hashCode();
- }
-
- @Override
- public String toString() {
- return key;
- }
- }
-
- private class OutputHandler implements Closeable {
- // Max single-line buffer before automatic wrap occurs.
- private static final int MAX_LINE_WIDTH = 1024 * 4;
-
- private final SpillWriter buffer;
-
- // internal stream.
- private final PrefixedWriter sint;
- // stdout
- private final PrefixedWriter sout;
- // stderr
- private final PrefixedWriter serr;
-
- // last used stream (so that we can flush it properly and prefixes are
not screwed up).
- private PrefixedWriter last;
-
- public OutputHandler() {
- buffer = new SpillWriter(() -> {
- try {
- return Files.createTempFile(spillDir, "spill-", ".tmp");
- } catch (IOException e) {
- throw new UncheckedIOException(e);
- }
- });
-
- Writer sink = buffer;
- if (verboseMode) {
- sink = new StdOutTeeWriter(buffer);
- }
-
- sint = new PrefixedWriter(" > ", sink, MAX_LINE_WIDTH);
- sout = new PrefixedWriter(" 1> ", sink, MAX_LINE_WIDTH);
- serr = new PrefixedWriter(" 2> ", sink, MAX_LINE_WIDTH);
- last = sint;
- }
-
- public void write(TestOutputEvent event) {
- write((event.getDestination() == TestOutputEvent.Destination.StdOut ?
sout : serr), event.getMessage());
- }
-
- public void write(String message) {
- write(sint, message);
- }
-
- public long length() throws IOException {
- return buffer.length();
- }
-
- private void write(PrefixedWriter out, String message) {
- try {
- if (out != last) {
- last.completeLine();
- last = out;
- }
- out.write(message);
- } catch (IOException e) {
- throw new UncheckedIOException("Unable to write to test output.",
e);
- }
- }
-
- public void copyTo(Writer out) throws IOException {
- flush();
- buffer.copyTo(out);
- }
-
- public void flush() throws IOException {
- sout.completeLine();
- serr.completeLine();
- buffer.flush();
- }
-
- @Override
- public void close() throws IOException {
- buffer.close();
- }
- }
-}
diff --git
a/buildSrc/src/main/java/org/apache/lucene/gradle/StdOutTeeWriter.java
b/buildSrc/src/main/java/org/apache/lucene/gradle/StdOutTeeWriter.java
deleted file mode 100644
index 20a4c8524f6..00000000000
--- a/buildSrc/src/main/java/org/apache/lucene/gradle/StdOutTeeWriter.java
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
- * 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.lucene.gradle;
-
-import java.io.IOException;
-import java.io.PrintStream;
-import java.io.Writer;
-
-class StdOutTeeWriter extends Writer {
- private final Writer delegate;
- private final PrintStream out = System.out;
-
- public StdOutTeeWriter(Writer delegate) {
- this.delegate = delegate;
- }
-
- @Override
- public void write(int c) throws IOException {
- delegate.write(c);
- out.write(c);
- }
-
- @Override
- public void write(char[] cbuf) throws IOException {
- delegate.write(cbuf);
- out.print(cbuf);
- }
-
- @Override
- public void write(String str) throws IOException {
- delegate.write(str);
- out.print(str);
- }
-
- @Override
- public void write(String str, int off, int len) throws IOException {
- delegate.write(str, off, len);
- out.append(str, off, len);
- }
-
- @Override
- public Writer append(CharSequence csq) throws IOException {
- delegate.append(csq);
- out.append(csq);
- return this;
- }
-
- @Override
- public Writer append(CharSequence csq, int start, int end) throws
IOException {
- delegate.append(csq, start, end);
- out.append(csq, start, end);
- return this;
- }
-
- @Override
- public Writer append(char c) throws IOException {
- delegate.append(c);
- out.append(c);
- return this;
- }
-
- @Override
- public void write(char[] cbuf, int off, int len) throws IOException {
- delegate.write(cbuf, off, len);
- out.print(new String(cbuf, off, len));
- }
-
- @Override
- public void flush() throws IOException {
- delegate.flush();
- out.flush();
- }
-
- @Override
- public void close() throws IOException {
- delegate.close();
- // Don't close the actual output.
- }
-}
diff --git a/dev-tools/README.txt b/dev-tools/README.txt
index db5a8e179b2..76ae0c52f3a 100644
--- a/dev-tools/README.txt
+++ b/dev-tools/README.txt
@@ -5,7 +5,6 @@ as to the usefulness of the tools.
Description of dev-tools/ contents:
-./missing-doclet -- JavaDoc validation doclet subproject
./doap/ -- Lucene and Solr project descriptors in DOAP RDF format.
./scripts/ -- Odds and ends for building releases, etc.
./test-patch/ -- Scripts for automatically validating patches
diff --git a/buildSrc/build.gradle b/gradle/conventions.gradle
similarity index 61%
rename from buildSrc/build.gradle
rename to gradle/conventions.gradle
index 91f88741322..fabc9b4cc58 100644
--- a/buildSrc/build.gradle
+++ b/gradle/conventions.gradle
@@ -15,24 +15,19 @@
* limitations under the License.
*/
-repositories {
- mavenCentral()
+configure(allprojects) {
+ tasks.register("tidy").configure {
+ description "Applies formatters and cleanups to sources."
+ group "verification"
+ }
}
-ext {
- // Minimum Java version required to compile buildSrc.
- minJavaVersion = JavaVersion.VERSION_11
-}
-
-// Make sure the build environment is consistent.
-apply from: file('../gradle/validation/check-environment.gradle')
-
-// Load common buildSrc and script deps.
-apply from: file("scriptDepVersions.gradle")
-
-dependencies {
- implementation gradleApi()
- implementation localGroovy()
-
- implementation
"commons-codec:commons-codec:${scriptDepVersions['commons-codec']}"
+// Locate script-relative resource folder. This is context-sensitive so pass
+// the right buildscript (top-level).
+configure(rootProject) {
+ ext {
+ scriptResources = { buildscript ->
+ return
file(buildscript.sourceFile.absolutePath.replaceAll('.gradle$', ""))
+ }
+ }
}
diff --git a/gradle/testing/defaults-tests.gradle
b/gradle/testing/defaults-tests.gradle
index d291ca85a40..f0af07c81de 100644
--- a/gradle/testing/defaults-tests.gradle
+++ b/gradle/testing/defaults-tests.gradle
@@ -18,7 +18,6 @@
import org.apache.tools.ant.taskdefs.condition.Os
import org.apache.tools.ant.types.Commandline
import org.gradle.api.tasks.testing.logging.*
-import org.apache.lucene.gradle.ErrorReportingTestListener
def resources = scriptResources(buildscript)
def verboseModeHookInstalled = false
@@ -173,7 +172,7 @@ allprojects {
}
def spillDir = getTemporaryDir().toPath()
- def listener = new ErrorReportingTestListener(test.testLogging,
spillDir, testOutputsDir.toPath(), verboseMode)
+ def listener =
buildinfra.newErrorReportingTestListener(test.testLogging, spillDir,
testOutputsDir.toPath(), verboseMode)
addTestOutputListener(listener)
addTestListener(listener)
diff --git a/gradle/testing/failed-tests-at-end.gradle
b/gradle/testing/failed-tests-at-end.gradle
index 5bffe9c9926..5b3381751d4 100644
--- a/gradle/testing/failed-tests-at-end.gradle
+++ b/gradle/testing/failed-tests-at-end.gradle
@@ -15,8 +15,6 @@
* limitations under the License.
*/
-import org.apache.lucene.gradle.ErrorReportingTestListener
-
// Display all failed tests at the end of the build.
def failedTests = new LinkedHashSet() // for dedupe due to weird afterTest
classMethod issue
@@ -29,7 +27,7 @@ def genFailInfo(def task, TestDescriptor desc) {
historyUrl += "&tests.test=$desc.name"
historyUrl += "
http://fucit.org/solr-jenkins-reports/history-trend-of-recent-failures.html#series/$name"
}
- def logName = ErrorReportingTestListener.getOutputLogName(desc.parent ?:
desc)
+ def logName = buildinfra.getOutputLogName(desc.parent ?: desc)
def output = file("${task.testOutputsDir}/${logName}")
def repro = "./gradlew ${task.project.path}:test --tests \"${name}\"
${task.project.testOptionsForReproduceLine}"
return ["name": name, "project": "${task.project.path}", "historyUrl":
historyUrl, "output": output, "reproduce": repro]
diff --git a/gradle/testing/profiling.gradle b/gradle/testing/profiling.gradle
index 34b3efe59fa..ce9e7d43e03 100644
--- a/gradle/testing/profiling.gradle
+++ b/gradle/testing/profiling.gradle
@@ -15,8 +15,6 @@
* limitations under the License.
*/
-import org.apache.lucene.gradle.ProfileResults;
-
def recordings = files()
allprojects {
@@ -48,7 +46,7 @@ allprojects {
gradle.buildFinished {
if (!recordings.isEmpty()) {
- ProfileResults.printReport(recordings.getFiles().collect { it.toString() },
+ buildinfra.profileResultsClass().printReport(recordings.getFiles().collect
{ it.toString() },
propertyOrDefault(ProfileResults.MODE_KEY,
ProfileResults.MODE_DEFAULT) as String,
Integer.parseInt(propertyOrDefault(ProfileResults.STACKSIZE_KEY,
ProfileResults.STACKSIZE_DEFAULT)),
Integer.parseInt(propertyOrDefault(ProfileResults.COUNT_KEY,
ProfileResults.COUNT_DEFAULT)),
diff --git a/gradle/validation/check-environment.gradle
b/gradle/validation/check-environment.gradle
index d9ea66b694e..6fcaf761a19 100644
--- a/gradle/validation/check-environment.gradle
+++ b/gradle/validation/check-environment.gradle
@@ -31,6 +31,7 @@ configure(rootProject) {
}
def currentJavaVersion = JavaVersion.current()
+ def minJavaVersion = rootProject.sourceCompatibility//
JavaVersion.VERSION_11 // TODO Write out java version
if (currentJavaVersion < minJavaVersion) {
throw new GradleException("At least Java ${minJavaVersion} is required,
you are running Java ${currentJavaVersion} "
+ "[${System.getProperty('java.vm.name')}
${System.getProperty('java.vm.version')}]")
diff --git a/gradle/validation/jar-checks.gradle
b/gradle/validation/jar-checks.gradle
index d416a9561fd..6c87c50f023 100644
--- a/gradle/validation/jar-checks.gradle
+++ b/gradle/validation/jar-checks.gradle
@@ -24,8 +24,6 @@
// Because of this all tasks here must always execute together, so they cannot
define task outputs.
// TODO: Rewrite the internal state to use state files containing the
ext.jarInfos and its referencedFiles
-import org.apache.commons.codec.digest.DigestUtils
-
// This should be false only for debugging.
def failOnError = true
@@ -152,7 +150,7 @@ subprojects {
jarName : file.toPath().getFileName().toString(),
path : file,
module : resolvedArtifact.moduleVersion,
- checksum : provider { new
DigestUtils(DigestUtils.sha1Digest).digestAsHex(file).trim() },
+ checksum : provider {
buildinfra.sha1Digest().digestAsHex(file).trim() },
// We keep track of the files referenced by this dependency
(sha, license, notice, etc.)
// so that we can determine unused dangling files later on.
referencedFiles: []
diff --git a/gradle/validation/owasp-dependency-check.gradle
b/gradle/validation/owasp-dependency-check.gradle
index eb5961e8269..f6352877dda 100644
--- a/gradle/validation/owasp-dependency-check.gradle
+++ b/gradle/validation/owasp-dependency-check.gradle
@@ -26,7 +26,7 @@ configure(rootProject) {
dependencyCheck {
failBuildOnCVSS = propertyOrDefault("validation.owasp.threshold", 7) as
Integer
formats = ['ALL']
- skipProjects = [':solr:solr-ref-guide', ':solr-missing-doclet']
+ skipProjects = [':solr:solr-ref-guide', ':missing-doclet']
skipConfigurations = ['unifiedClasspath', 'permitUnusedDeclared']
suppressionFile = file("${resources}/exclusions.xml")
analyzers {
diff --git a/gradle/validation/rat-sources.gradle
b/gradle/validation/rat-sources.gradle
index 91f2278e249..577529a9c16 100644
--- a/gradle/validation/rat-sources.gradle
+++ b/gradle/validation/rat-sources.gradle
@@ -96,10 +96,10 @@ allprojects {
exclude "dev-tools/scripts/README.md"
exclude "dev-tools/scripts/create_line_file_docs.py"
- // The root project also includes patterns for the
boostrap (buildSrc) and composite
+ // The root project also includes patterns for the include
composite
// projects. Include their sources in the scan.
- include "buildSrc/src/**"
- include "dev-tools/solr-missing-doclet/src/**"
+ include "build-tools/build-infra/src/**"
+ include "build-tools/missing-doclet/src/**"
break
case ":solr:modules:clustering":
diff --git a/gradle/validation/spotless.gradle
b/gradle/validation/spotless.gradle
index 95607c67327..76fecdfad98 100644
--- a/gradle/validation/spotless.gradle
+++ b/gradle/validation/spotless.gradle
@@ -20,9 +20,7 @@
* spotless and Google Java Format.
*/
-def resources = scriptResources(buildscript)
-
-configure(project(":solr").subprojects) { prj ->
+configure(allprojects) { prj ->
plugins.withType(JavaPlugin) {
prj.apply plugin: 'com.diffplug.spotless'
@@ -95,23 +93,20 @@ configure(project(":solr").subprojects) { prj ->
// Emit a custom message about how to fix formatting errors.
tasks.matching { task -> task.name == "spotlessJavaCheck" }.configureEach {
- runToFixMessage.set("\nIMPORTANT: run the top-level './gradlew tidy' to
format code automatically (see help/formatting.txt for more info).")
+ it.runToFixMessage.set("\nIMPORTANT: run the top-level './gradlew tidy' to
format code automatically (see help/formatting.txt for more info).")
}
- // Add an alias to 'spotlessApply' simply called 'tidy' and wire up
- // spotlessCheck to convention's check.
- task tidy() {
- description "Applies formatters and cleanups to sources."
- group "verification"
+ // Hook up spotless to tidy and check tasks.
+
+ tasks.matching { it.name == "tidy" }.configureEach { v ->
+ v.dependsOn tasks.matching { it.name == "spotlessApply" }
}
- tasks.matching { task -> task.name == "spotlessApply" }.configureEach { v ->
- tidy.dependsOn v
- v.dependsOn ":checkJdkInternalsExportedToGradle"
+ tasks.matching { it.name == "check" }.configureEach { v ->
+ v.dependsOn tasks.matching { it.name == "spotlessCheck" }
}
- tasks.matching { task -> task.name == "spotlessCheck" }.configureEach { v ->
- check.dependsOn v
+ tasks.matching { task -> task.name in ["spotlessApply", "spotlessCheck"]
}.configureEach { v ->
v.dependsOn ":checkJdkInternalsExportedToGradle"
}
}
diff --git a/gradlew b/gradlew
index c0f76e91038..0aa671a76c2 100755
--- a/gradlew
+++ b/gradlew
@@ -158,7 +158,7 @@ fi
GRADLE_WRAPPER_JAR="$APP_HOME/gradle/wrapper/gradle-wrapper.jar"
if [ ! -e "$GRADLE_WRAPPER_JAR" ]; then
- "$JAVACMD" $JAVA_OPTS
"$APP_HOME/buildSrc/src/main/java/org/apache/lucene/gradle/WrapperDownloader.java"
"$GRADLE_WRAPPER_JAR"
+ "$JAVACMD" $JAVA_OPTS
"$APP_HOME/build-tools/build-infra/src/main/java/org/apache/lucene/gradle/WrapperDownloader.java"
"$GRADLE_WRAPPER_JAR"
WRAPPER_STATUS=$?
if [ "$WRAPPER_STATUS" -eq 1 ]; then
echo "ERROR: Something went wrong. Make sure you're using Java version
between 11 and 21."
@@ -173,7 +173,7 @@ CLASSPATH=$GRADLE_WRAPPER_JAR
# START OF LUCENE CUSTOMIZATION
# Generate gradle.properties if they don't exist
if [ ! -e "$APP_HOME/gradle.properties" ]; then
- "$JAVACMD" $JAVA_OPTS
"$APP_HOME/buildSrc/src/main/java/org/apache/lucene/gradle/GradlePropertiesGenerator.java"
"$APP_HOME/gradle/template.gradle.properties" "$APP_HOME/gradle.properties"
+ "$JAVACMD" $JAVA_OPTS
"$APP_HOME/build-tools/build-infra/src/main/java/org/apache/lucene/gradle/GradlePropertiesGenerator.java"
"$APP_HOME/gradle/template.gradle.properties" "$APP_HOME/gradle.properties"
GENERATOR_STATUS=$?
if [ "$GENERATOR_STATUS" -ne 0 ]; then
exit $GENERATOR_STATUS
diff --git a/gradlew.bat b/gradlew.bat
index 172618e3ea4..938e3ce94ee 100644
--- a/gradlew.bat
+++ b/gradlew.bat
@@ -76,7 +76,7 @@ goto fail
@rem LUCENE-9266: verify and download the gradle wrapper jar if we don't have
one.
set GRADLE_WRAPPER_JAR=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
IF NOT EXIST "%GRADLE_WRAPPER_JAR%" (
- "%JAVA_EXE%" %JAVA_OPTS%
"%APP_HOME%/buildSrc/src/main/java/org/apache/lucene/gradle/WrapperDownloader.java"
"%GRADLE_WRAPPER_JAR%"
+ "%JAVA_EXE%" %JAVA_OPTS%
"%APP_HOME%/build-tools/build-infra/src/main/java/org/apache/lucene/gradle/WrapperDownloader.java"
"%GRADLE_WRAPPER_JAR%"
IF %ERRORLEVEL% EQU 1 goto failWithJvmMessage
IF %ERRORLEVEL% NEQ 0 goto fail
)
@@ -89,7 +89,7 @@ set CLASSPATH=%GRADLE_WRAPPER_JAR%
IF NOT EXIST "%APP_HOME%\gradle.properties" (
@rem local expansion is needed to check ERRORLEVEL inside control blocks.
setlocal enableDelayedExpansion
- "%JAVA_EXE%" %JAVA_OPTS%
"%APP_HOME%/buildSrc/src/main/java/org/apache/lucene/gradle/GradlePropertiesGenerator.java"
"%APP_HOME%\gradle\template.gradle.properties" "%APP_HOME%\gradle.properties"
+ "%JAVA_EXE%" %JAVA_OPTS%
"%APP_HOME%/build-tools/build-infra/src/main/java/org/apache/lucene/gradle/GradlePropertiesGenerator.java"
"%APP_HOME%\gradle\template.gradle.properties" "%APP_HOME%\gradle.properties"
IF %ERRORLEVEL% NEQ 0 goto fail
endlocal
)
diff --git a/settings.gradle b/settings.gradle
index b39d92b1234..a9dd4a99ba1 100644
--- a/settings.gradle
+++ b/settings.gradle
@@ -20,6 +20,8 @@ pluginManagement {
mavenCentral()
gradlePluginPortal()
}
+
+ includeBuild("build-tools/build-infra")
}
plugins {
@@ -31,7 +33,7 @@ apply from: file('gradle/develocity.gradle')
rootProject.name = "solr-root"
-includeBuild("dev-tools/solr-missing-doclet")
+includeBuild("build-tools/missing-doclet")
include "solr:api"
include "solr:solrj"
diff --git a/solr/distribution/build.gradle b/solr/distribution/build.gradle
index 8ebc5872f53..8609ffab173 100644
--- a/solr/distribution/build.gradle
+++ b/solr/distribution/build.gradle
@@ -15,8 +15,6 @@
* limitations under the License.
*/
-import org.apache.lucene.gradle.Checksum
-
import java.nio.charset.StandardCharsets
import java.nio.file.Files
@@ -68,8 +66,7 @@ def fullDistTarTask =
rootProject.getTasksByName("fullDistTar", true)[0]
def slimDistTarTask = rootProject.getTasksByName("slimDistTar", true)[0]
// Compute checksums for release archives.
-task computeChecksums(type: Checksum) {
- algorithm = Checksum.Algorithm.SHA512
+task computeChecksums(type: buildinfra.checksumClass()) {
files = objects.fileCollection()
[