S19: consume versioned engineering resources and move landscape documentation
All checks were successful
Build, test and publish / verify (push) Successful in 8m54s
All checks were successful
Build, test and publish / verify (push) Successful in 8m54s
This commit is contained in:
@@ -1,131 +0,0 @@
|
||||
import com.palantir.javaformat.java.Formatter;
|
||||
import com.palantir.javaformat.java.JavaFormatterOptions;
|
||||
import java.nio.file.*;
|
||||
import java.security.MessageDigest;
|
||||
import java.util.*;
|
||||
import org.openrewrite.*;
|
||||
import org.openrewrite.internal.InMemoryLargeSourceSet;
|
||||
import org.openrewrite.text.*;
|
||||
|
||||
/** Source-launcher bootstrap: no project-specific artifact is resolved or installed. */
|
||||
public class Format {
|
||||
public static void main(String[] args) throws Exception {
|
||||
Path root = Path.of(args[0]).toAbsolutePath().normalize();
|
||||
boolean check = switch (args[1]) {
|
||||
case "check" -> true;
|
||||
case "apply" -> false;
|
||||
default -> throw new IllegalArgumentException("format.mode must be apply or check");
|
||||
};
|
||||
Path cacheFile = root.resolve("target/palantir-cache.properties");
|
||||
var cache = new Properties();
|
||||
if (Files.exists(cacheFile)) {
|
||||
try (var input = Files.newInputStream(cacheFile)) {
|
||||
cache.load(input);
|
||||
}
|
||||
}
|
||||
String configuration = digest(Files.readString(root.resolve("pom.xml"))
|
||||
+ Files.readString(root.resolve("tooling/format/Format.java"))
|
||||
+ System.getProperty("java.version")
|
||||
+ System.getProperty("java.class.path"));
|
||||
if (!configuration.equals(cache.getProperty("configuration"))) cache.clear();
|
||||
cache.setProperty("configuration", configuration);
|
||||
List<SourceFile> sources = new ArrayList<>();
|
||||
for (String directory :
|
||||
List.of("agiledancers-be/src/main/java", "agiledancers-be/src/test/java", "ci", "tooling/format")) {
|
||||
try (var paths = Files.walk(root.resolve(directory))) {
|
||||
for (Path path : paths.filter(p -> p.toString().endsWith(".java"))
|
||||
.sorted()
|
||||
.toList()) {
|
||||
try {
|
||||
String content = Files.readString(path);
|
||||
String key = root.relativize(path).toString();
|
||||
if (!digest(content).equals(cache.getProperty(key))) {
|
||||
sources.add(PlainText.builder()
|
||||
.sourcePath(root.relativize(path))
|
||||
.text(content)
|
||||
.build());
|
||||
}
|
||||
} catch (Exception error) {
|
||||
throw new IllegalStateException(path + ": " + error.getMessage(), error);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
var context = new InMemoryExecutionContext(error -> {
|
||||
throw new IllegalStateException("Formatting failed: " + error.getMessage(), error);
|
||||
});
|
||||
var results = new PalantirRecipe()
|
||||
.run(new InMemoryLargeSourceSet(sources), context)
|
||||
.getChangeset()
|
||||
.getAllResults();
|
||||
for (Result result : results) {
|
||||
System.out.println((check ? "Needs formatting: " : "Formatted: ")
|
||||
+ result.getAfter().getSourcePath());
|
||||
}
|
||||
if (check && !results.isEmpty()) {
|
||||
throw new IllegalStateException("Run mvn -N exec:exec@format to apply Palantir formatting.");
|
||||
}
|
||||
// Complete parsing/formatting before writing any maintained file. Each replacement is atomic.
|
||||
if (!check) {
|
||||
for (Result result : results) {
|
||||
Path destination = root.resolve(result.getAfter().getSourcePath());
|
||||
Path temporary = Files.createTempFile(destination.getParent(), ".palantir-", ".tmp");
|
||||
try {
|
||||
Files.writeString(temporary, result.getAfter().printAll());
|
||||
Files.setPosixFilePermissions(temporary, Files.getPosixFilePermissions(destination));
|
||||
Files.move(
|
||||
temporary,
|
||||
destination,
|
||||
StandardCopyOption.ATOMIC_MOVE,
|
||||
StandardCopyOption.REPLACE_EXISTING);
|
||||
} finally {
|
||||
Files.deleteIfExists(temporary);
|
||||
}
|
||||
}
|
||||
}
|
||||
for (SourceFile source : sources) {
|
||||
cache.setProperty(
|
||||
source.getSourcePath().toString(), digest(Files.readString(root.resolve(source.getSourcePath()))));
|
||||
}
|
||||
Files.createDirectories(cacheFile.getParent());
|
||||
try (var output = Files.newOutputStream(cacheFile)) {
|
||||
cache.store(output, "Successfully formatted content only");
|
||||
}
|
||||
System.out.println(
|
||||
"Palantir " + args[1] + ": " + sources.size() + " Java files, " + results.size() + " differences");
|
||||
}
|
||||
|
||||
static String digest(String value) throws Exception {
|
||||
return HexFormat.of()
|
||||
.formatHex(MessageDigest.getInstance("SHA-256")
|
||||
.digest(value.getBytes(java.nio.charset.StandardCharsets.UTF_8)));
|
||||
}
|
||||
|
||||
public static final class PalantirRecipe extends Recipe {
|
||||
public String getDisplayName() {
|
||||
return "Palantir Java Format";
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return "Apply the pinned Palantir engine and its native import handling.";
|
||||
}
|
||||
|
||||
public TreeVisitor<?, ExecutionContext> getVisitor() {
|
||||
return new PlainTextVisitor<ExecutionContext>() {
|
||||
final Formatter formatter = Formatter.createFormatter(JavaFormatterOptions.builder()
|
||||
.style(JavaFormatterOptions.Style.PALANTIR)
|
||||
.formatJavadoc(false)
|
||||
.build());
|
||||
|
||||
@Override
|
||||
public PlainText visitText(PlainText text, ExecutionContext context) {
|
||||
try {
|
||||
return text.withText(formatter.formatSourceAndFixImports(text.getText()));
|
||||
} catch (Exception | LinkageError error) {
|
||||
throw new IllegalStateException(text.getSourcePath() + ": " + error, error);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,53 +0,0 @@
|
||||
"""Integration checks against an isolated checkout; run python3 tooling/format/test.py."""
|
||||
from pathlib import Path
|
||||
import shutil
|
||||
import subprocess
|
||||
import tempfile
|
||||
|
||||
root = Path(__file__).resolve().parents[2]
|
||||
with tempfile.TemporaryDirectory(prefix="palantir-test-") as temporary:
|
||||
fixture = Path(temporary)
|
||||
for name in ("pom.xml", ".mvn", "tooling/format"):
|
||||
source = root / name
|
||||
destination = fixture / name
|
||||
if source.is_dir():
|
||||
shutil.copytree(source, destination)
|
||||
else:
|
||||
shutil.copy2(source, destination)
|
||||
for name in ("agiledancers-be/src/main/java", "agiledancers-be/src/test/java", "ci/runner"):
|
||||
(fixture / name).mkdir(parents=True)
|
||||
source = fixture / "ci/runner/Example.java"
|
||||
original = "import java.util.List;\nclass Example{String text=\"héllo\";int value(){return 1;}}\n"
|
||||
source.write_text(original)
|
||||
|
||||
def run(mode, success=True):
|
||||
result = subprocess.run(
|
||||
["mvn", "-N", "-B", "-ntp", "exec:exec@format", "-Dformat.mode=" + mode],
|
||||
cwd=fixture, text=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
|
||||
assert (result.returncode == 0) == success, result.stdout
|
||||
return result.stdout
|
||||
|
||||
output = run("check", False)
|
||||
assert "ci/runner/Example.java" in output and "mvn -N exec:exec@format" in output
|
||||
assert source.read_text() == original
|
||||
run("apply")
|
||||
formatted = source.read_text()
|
||||
assert "import java.util.List" not in formatted and "héllo" in formatted
|
||||
run("check")
|
||||
run("apply")
|
||||
assert source.read_text() == formatted
|
||||
# Force a full (uncached) second pass to prove engine idempotence.
|
||||
(fixture / "target/palantir-cache.properties").unlink()
|
||||
run("check")
|
||||
source.write_text(formatted + "class Broken { ??? }\n")
|
||||
invalid = source.read_bytes()
|
||||
output = run("apply", False)
|
||||
assert "ci/runner/Example.java" in output
|
||||
assert source.read_bytes() == invalid
|
||||
# A new file is discovered even after a successful cached check.
|
||||
source.write_text(formatted)
|
||||
extra = fixture / "ci/New.java"
|
||||
extra.write_text("class New{}")
|
||||
run("check", False)
|
||||
assert extra.read_text() == "class New{}"
|
||||
print("PASS: check is read-only, apply/check agree, imports, UTF-8, idempotence, parser errors, new files")
|
||||
Reference in New Issue
Block a user