From 00d83a3d8b0d827e5e6ecee9cdc457b502f0e470 Mon Sep 17 00:00:00 2001 From: James Judd Date: Fri, 26 Jul 2024 23:14:55 -0600 Subject: [PATCH 1/3] Finish and fix the addition of Bazel worker support --- play-routes-compiler/BUILD.bazel | 2 + .../scala/CommandLinePlayRoutesCompiler.scala | 30 ++- test/BUILD.bazel | 2 +- .../build/buildjar/jarhelper/BUILD.bazel | 13 + .../build/buildjar/jarhelper/JarCreator.java | 253 ++++++++++++++++++ .../build/buildjar/jarhelper/JarHelper.java | 244 +++++++++++++++++ 6 files changed, 537 insertions(+), 7 deletions(-) create mode 100644 third_party/bazel/src/java_tools/buildjar/java/com/google/devtools/build/buildjar/jarhelper/BUILD.bazel create mode 100644 third_party/bazel/src/java_tools/buildjar/java/com/google/devtools/build/buildjar/jarhelper/JarCreator.java create mode 100644 third_party/bazel/src/java_tools/buildjar/java/com/google/devtools/build/buildjar/jarhelper/JarHelper.java diff --git a/play-routes-compiler/BUILD.bazel b/play-routes-compiler/BUILD.bazel index c583158..7e5e908 100644 --- a/play-routes-compiler/BUILD.bazel +++ b/play-routes-compiler/BUILD.bazel @@ -13,8 +13,10 @@ scala_library( tags = ["maven_coordinates=com.lucidchart:" + artifact_id + ":{pom_version}"], visibility = ["//visibility:public"], deps = [ + "//third_party/bazel/src/java_tools/buildjar/java/com/google/devtools/build/buildjar/jarhelper", "@play_routes_compiler_cli_maven//:com_github_scopt_scopt_3", "@play_routes_compiler_cli_maven//:org_playframework_play_routes_compiler_3", + "@rules_scala_annex//src/main/scala/higherkindness/rules_scala/common/error", "@rules_scala_annex//src/main/scala/higherkindness/rules_scala/common/worker", ], ) diff --git a/play-routes-compiler/src/main/scala/CommandLinePlayRoutesCompiler.scala b/play-routes-compiler/src/main/scala/CommandLinePlayRoutesCompiler.scala index 217f61c..89f7377 100644 --- a/play-routes-compiler/src/main/scala/CommandLinePlayRoutesCompiler.scala +++ b/play-routes-compiler/src/main/scala/CommandLinePlayRoutesCompiler.scala @@ -1,5 +1,7 @@ package rulesplayroutes.routes +import com.google.devtools.build.buildjar.jarhelper.JarCreator +import higherkindness.rules_scala.common.error.AnnexWorkerError import higherkindness.rules_scala.common.worker.WorkerMain import java.io.{File, PrintStream} import java.nio.file.{Files, Paths} @@ -15,6 +17,7 @@ object CommandLinePlayRoutesCompiler extends WorkerMain[Unit] { case class Config( sources: Seq[File] = Seq.empty[File], generatedDirectory: File = new File("."), + outputSrcJar: File = new File("."), additionalImports: Seq[String] = Seq.empty[String], routesGenerator: RoutesGenerator = InjectedRoutesGenerator, generateReverseRouter: Boolean = false, @@ -29,6 +32,10 @@ object CommandLinePlayRoutesCompiler extends WorkerMain[Unit] { config.copy(generatedDirectory = value) }.text("directory to output compiled routes to") + arg[File]("").required().action { (value, config) => + config.copy(outputSrcJar = value) + }.text("file to output srcjar containing compiled routes to") + arg[Seq[File]](",...").unbounded().required().action { (value, config) => config.copy(sources = value) }.text("routes to compile") @@ -104,17 +111,28 @@ object CommandLinePlayRoutesCompiler extends WorkerMain[Unit] { } } + def generateJar(config: Config): Unit = { + val jarCreator = new JarCreator(config.outputSrcJar.toPath()) + jarCreator.addDirectory(config.generatedDirectory.toPath()) + jarCreator.setCompression(false) + jarCreator.setNormalize(true) + jarCreator.setVerbose(false) + jarCreator.execute() + } + override def init(args: Option[Array[String]]): Unit = () protected def work(ctx: Unit, args: Array[String], out: PrintStream): Unit = { - val isSuccess = parser.parse(args, Config()) - .map(compilePlayRoutes) - .getOrElse(false) + val finalArgs = args.toList.flatMap { + case arg if arg.startsWith("@") => Files.readAllLines(Paths.get(arg.tail)).asScala + case arg => Array(arg) + } + val config = parser.parse(finalArgs, Config()).getOrElse(throw new AnnexWorkerError(1)) - if (isSuccess) { - System.exit(0) + if (compilePlayRoutes(config)) { + generateJar(config) } else { - System.exit(1) + throw new AnnexWorkerError(1) } } } \ No newline at end of file diff --git a/test/BUILD.bazel b/test/BUILD.bazel index a37b6a7..a9e9130 100644 --- a/test/BUILD.bazel +++ b/test/BUILD.bazel @@ -1,7 +1,7 @@ # Borrowed from lucidsoftware/rules_play_routes but using //play-routes-compiler for the compiler cli load("@rules_scala_annex//rules:scala.bzl", "scala_library", "scala_test") -load("@io_bazel_rules_play_routes//play-routes:play-routes.bzl", "play_routes") +load("@rules_play_routes//play-routes:play-routes.bzl", "play_routes") play_routes( name = "play-routes", diff --git a/third_party/bazel/src/java_tools/buildjar/java/com/google/devtools/build/buildjar/jarhelper/BUILD.bazel b/third_party/bazel/src/java_tools/buildjar/java/com/google/devtools/build/buildjar/jarhelper/BUILD.bazel new file mode 100644 index 0000000..cbf8d2c --- /dev/null +++ b/third_party/bazel/src/java_tools/buildjar/java/com/google/devtools/build/buildjar/jarhelper/BUILD.bazel @@ -0,0 +1,13 @@ +# Copyright 2014 The Bazel Authors. Licensed under Apache License, Version 2.0 +load("@rules_java//java:defs.bzl", "java_library") + +licenses(["notice"]) + +java_library( + name = "jarhelper", + srcs = [ + "JarCreator.java", + "JarHelper.java", + ], + visibility = ["//visibility:public"], +) diff --git a/third_party/bazel/src/java_tools/buildjar/java/com/google/devtools/build/buildjar/jarhelper/JarCreator.java b/third_party/bazel/src/java_tools/buildjar/java/com/google/devtools/build/buildjar/jarhelper/JarCreator.java new file mode 100644 index 0000000..848165d --- /dev/null +++ b/third_party/bazel/src/java_tools/buildjar/java/com/google/devtools/build/buildjar/jarhelper/JarCreator.java @@ -0,0 +1,253 @@ +// Copyright 2014 The Bazel Authors. All rights reserved. +// +// Licensed 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 com.google.devtools.build.buildjar.jarhelper; + +import java.io.BufferedOutputStream; +import java.io.ByteArrayOutputStream; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.io.UncheckedIOException; +import java.nio.file.FileVisitResult; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.nio.file.SimpleFileVisitor; +import java.nio.file.attribute.BasicFileAttributes; +import java.util.Map; +import java.util.TreeMap; +import java.util.jar.Attributes; +import java.util.jar.JarOutputStream; +import java.util.jar.Manifest; + +/** + * A class for creating Jar files. Allows normalization of Jar entries by setting their timestamp to + * the DOS epoch. All Jar entries are sorted alphabetically. + */ +public class JarCreator extends JarHelper { + + // Map from Jar entry names to files. Use TreeMap so we can establish a canonical order for the + // entries regardless in what order they get added. + private final TreeMap jarEntries = new TreeMap<>(); + private String manifestFile; + private String mainClass; + private String targetLabel; + private String injectingRuleKind; + + /** @deprecated use {@link JarCreator(Path)} instead */ + @Deprecated + public JarCreator(String fileName) { + this(Paths.get(fileName)); + } + + public JarCreator(Path path) { + super(path); + } + + /** + * Adds an entry to the Jar file, normalizing the name. + * + * @param entryName the name of the entry in the Jar file + * @param path the path of the input for the entry + * @return true iff a new entry was added + */ + public boolean addEntry(String entryName, Path path) { + if (entryName.startsWith("/")) { + entryName = entryName.substring(1); + } else if (entryName.length() >= 3 + && Character.isLetter(entryName.charAt(0)) + && entryName.charAt(1) == ':' + && (entryName.charAt(2) == '\\' || entryName.charAt(2) == '/')) { + // Windows absolute path, e.g. "D:\foo" or "e:/blah". + // Windows paths are case-insensitive, and support both backslashes and forward slashes. + entryName = entryName.substring(3); + } else if (entryName.startsWith("./")) { + entryName = entryName.substring(2); + } + return jarEntries.put(entryName, path) == null; + } + + /** + * Adds an entry to the Jar file, normalizing the name. + * + * @param entryName the name of the entry in the Jar file + * @param fileName the name of the input file for the entry + * @return true iff a new entry was added + */ + public boolean addEntry(String entryName, String fileName) { + return addEntry(entryName, Paths.get(fileName)); + } + + /** @deprecated prefer {@link #addDirectory(Path)} */ + @Deprecated + public void addDirectory(String directory) { + addDirectory(Paths.get(directory)); + } + + /** + * Adds the contents of a directory to the Jar file. All files below this directory will be added + * to the Jar file using the name relative to the directory as the name for the Jar entry. + * + * @param directory the directory to add to the jar + */ + public void addDirectory(Path directory) { + if (!Files.exists(directory)) { + throw new IllegalArgumentException("directory does not exist: " + directory); + } + try { + Files.walkFileTree( + directory, + new SimpleFileVisitor() { + + @Override + public FileVisitResult preVisitDirectory(Path path, BasicFileAttributes attrs) + throws IOException { + if (!path.equals(directory)) { + // For consistency with legacy behaviour, include entries for directories except for + // the root. + addEntry(path, /* isDirectory= */ true); + } + return FileVisitResult.CONTINUE; + } + + @Override + public FileVisitResult visitFile(Path path, BasicFileAttributes attrs) + throws IOException { + addEntry(path, /* isDirectory= */ false); + return FileVisitResult.CONTINUE; + } + + void addEntry(Path path, boolean isDirectory) { + StringBuilder sb = new StringBuilder(); + boolean first = true; + for (Path entry : directory.relativize(path)) { + if (!first) { + // use `/` as the directory separator for jar paths, even on Windows + sb.append('/'); + } + sb.append(entry.getFileName()); + first = false; + } + if (isDirectory) { + sb.append('/'); + } + jarEntries.put(sb.toString(), path); + } + }); + } catch (IOException e) { + throw new UncheckedIOException(e); + } + } + + /** + * Sets the main.class entry for the manifest. A value of null (the default) will + * omit the entry. + * + * @param mainClass the fully qualified name of the main class + */ + public void setMainClass(String mainClass) { + this.mainClass = mainClass; + } + + public void setJarOwner(String targetLabel, String injectingRuleKind) { + this.targetLabel = targetLabel; + this.injectingRuleKind = injectingRuleKind; + } + + /** + * Sets filename for the manifest content. If this is set the manifest will be read from this file + * otherwise the manifest content will get generated on the fly. + * + * @param manifestFile the filename of the manifest file. + */ + public void setManifestFile(String manifestFile) { + this.manifestFile = manifestFile; + } + + private byte[] manifestContent() throws IOException { + if (manifestFile != null) { + try (FileInputStream in = new FileInputStream(manifestFile)) { + return manifestContentImpl(new Manifest(in)); + } + } else { + return manifestContentImpl(new Manifest()); + } + } + + private byte[] manifestContentImpl(Manifest manifest) throws IOException { + Attributes attributes = manifest.getMainAttributes(); + attributes.put(Attributes.Name.MANIFEST_VERSION, "1.0"); + Attributes.Name createdBy = new Attributes.Name("Created-By"); + if (attributes.getValue(createdBy) == null) { + attributes.put(createdBy, "bazel"); + } + if (mainClass != null) { + attributes.put(Attributes.Name.MAIN_CLASS, mainClass); + } + if (targetLabel != null) { + attributes.put(JarHelper.TARGET_LABEL, targetLabel); + } + if (injectingRuleKind != null) { + attributes.put(JarHelper.INJECTING_RULE_KIND, injectingRuleKind); + } + ByteArrayOutputStream out = new ByteArrayOutputStream(); + manifest.write(out); + return out.toByteArray(); + } + + /** + * Executes the creation of the Jar file. + * + * @throws IOException if the Jar cannot be written or any of the entries cannot be read. + */ + public void execute() throws IOException { + try (OutputStream os = Files.newOutputStream(jarPath); + BufferedOutputStream bos = new BufferedOutputStream(os); + JarOutputStream out = new JarOutputStream(bos)) { + + // Create the manifest entry in the Jar file + writeManifestEntry(out, manifestContent()); + + for (Map.Entry entry : jarEntries.entrySet()) { + copyEntry(out, entry.getKey(), entry.getValue()); + } + } + } + + /** A simple way to create Jar file using the JarCreator class. */ + public static void main(String[] args) { + if (args.length < 1) { + System.err.println("usage: CreateJar output [root directories]"); + System.exit(1); + } + String output = args[0]; + JarCreator createJar = new JarCreator(output); + for (int i = 1; i < args.length; i++) { + createJar.addDirectory(args[i]); + } + createJar.setCompression(true); + createJar.setNormalize(true); + createJar.setVerbose(true); + long start = System.currentTimeMillis(); + try { + createJar.execute(); + } catch (IOException e) { + e.printStackTrace(); + System.exit(1); + } + long stop = System.currentTimeMillis(); + System.err.println((stop - start) + "ms."); + } +} \ No newline at end of file diff --git a/third_party/bazel/src/java_tools/buildjar/java/com/google/devtools/build/buildjar/jarhelper/JarHelper.java b/third_party/bazel/src/java_tools/buildjar/java/com/google/devtools/build/buildjar/jarhelper/JarHelper.java new file mode 100644 index 0000000..96a5066 --- /dev/null +++ b/third_party/bazel/src/java_tools/buildjar/java/com/google/devtools/build/buildjar/jarhelper/JarHelper.java @@ -0,0 +1,244 @@ +// Copyright 2014 The Bazel Authors. All rights reserved. +// +// Licensed 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 com.google.devtools.build.buildjar.jarhelper; + +import java.io.FileNotFoundException; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.time.LocalDateTime; +import java.time.ZoneId; +import java.util.HashSet; +import java.util.Set; +import java.util.jar.Attributes; +import java.util.jar.JarEntry; +import java.util.jar.JarFile; +import java.util.jar.JarOutputStream; +import java.util.zip.CRC32; + +/** + * A simple helper class for creating Jar files. All Jar entries are sorted alphabetically. Allows + * normalization of Jar entries by setting the timestamp of non-.class files to the DOS epoch. + * Timestamps of .class files are set to the DOS epoch + 2 seconds (The zip timestamp granularity) + * Adjusting the timestamp for .class files is necessary since otherwise javac will recompile java + * files if both the java file and its .class file are present. + */ +public class JarHelper { + + public static final String MANIFEST_DIR = "META-INF/"; + public static final String MANIFEST_NAME = JarFile.MANIFEST_NAME; + + /** + * Normalize timestamps to 2010-1-1. + * + *

The ZIP format uses MS-DOS timestamps (see APPNOTE.TXT) which use + * 1980-1-1 as the epoch, but {@link ZipEntry#setTime(long)} expects milliseconds since the unix + * epoch (1970-1-1). To work around this, {@link ZipEntry} uses portability-reducing ZIP + * extensions to store pre-1980 timestamps, which can occasionally issues. For that reason, using a + * fixed post-1980 timestamp is preferred to e.g. calling {@code setTime(0)}. At Google, the + * timestamp of 2010-1-1 is used by convention in deterministic jar archives. + */ + @SuppressWarnings("GoodTime-ApiWithNumericTimeUnit") // Use setTime(LocalDateTime) in Java > 9 + public static final long DEFAULT_TIMESTAMP = + LocalDateTime.of(2010, 1, 1, 0, 0, 0) + .atZone(ZoneId.systemDefault()) + .toInstant() + .toEpochMilli(); + // These attributes are used by JavaBuilder, Turbine, and ijar. + // They must all be kept in sync. + public static final Attributes.Name TARGET_LABEL = new Attributes.Name("Target-Label"); + public static final Attributes.Name INJECTING_RULE_KIND = + new Attributes.Name("Injecting-Rule-Kind"); + + // ZIP timestamps have a resolution of 2 seconds. + // see http://www.info-zip.org/FAQ.html#limits + public static final long MINIMUM_TIMESTAMP_INCREMENT = 2000L; + + // The path to the Jar we want to create + protected final Path jarPath; + + // The properties to describe how to create the Jar + protected boolean normalize; + protected int storageMethod = JarEntry.DEFLATED; + protected boolean verbose = false; + + // The state needed to create the Jar + protected final Set names = new HashSet<>(); + + public JarHelper(Path path) { + jarPath = path; + } + + /** + * Enables or disables the Jar entry normalization. + * + * @param normalize If true the timestamps of Jar entries will be set to the DOS epoch. + */ + public void setNormalize(boolean normalize) { + this.normalize = normalize; + } + + /** + * Enables or disables compression for the Jar file entries. + * + * @param compression if true enables compressions for the Jar file entries. + */ + public void setCompression(boolean compression) { + storageMethod = compression ? JarEntry.DEFLATED : JarEntry.STORED; + } + + /** + * Enables or disables verbose messages. + * + * @param verbose if true enables verbose messages. + */ + public void setVerbose(boolean verbose) { + this.verbose = verbose; + } + + /** + * Returns the normalized timestamp for a jar entry based on its name. This is necessary since + * javac will, when loading a class X, prefer a source file to a class file, if both files have + * the same timestamp. Therefore, we need to adjust the timestamp for class files to slightly + * after the normalized time. + * + * @param name The name of the file for which we should return the normalized timestamp. + * @return the time for a new Jar file entry in milliseconds since the epoch. + */ + private long normalizedTimestamp(String name) { + if (name.endsWith(".class")) { + return DEFAULT_TIMESTAMP + MINIMUM_TIMESTAMP_INCREMENT; + } else { + return DEFAULT_TIMESTAMP; + } + } + + /** + * Returns the time for a new Jar file entry in milliseconds since the epoch. Uses {@link + * JarCreator#DEFAULT_TIMESTAMP} for normalized entries, {@link System#currentTimeMillis()} + * otherwise. + * + * @param filename The name of the file for which we are entering the time + * @return the time for a new Jar file entry in milliseconds since the epoch. + */ + protected long newEntryTimeMillis(String filename) { + return normalize ? normalizedTimestamp(filename) : System.currentTimeMillis(); + } + + /** + * Writes an entry with specific contents to the jar. Directory entries must include the trailing + * '/'. + */ + protected void writeEntry(JarOutputStream out, String name, byte[] content) throws IOException { + if (names.add(name)) { + // Create a new entry + JarEntry entry = new JarEntry(name); + entry.setTime(newEntryTimeMillis(name)); + int size = content.length; + entry.setSize(size); + if (size == 0) { + entry.setMethod(JarEntry.STORED); + entry.setCrc(0); + out.putNextEntry(entry); + } else { + entry.setMethod(storageMethod); + if (storageMethod == JarEntry.STORED) { + CRC32 crc = new CRC32(); + crc.update(content); + entry.setCrc(crc.getValue()); + } + out.putNextEntry(entry); + out.write(content); + } + out.closeEntry(); + } + } + + /** + * Writes a standard Java manifest entry into the JarOutputStream. This includes the directory + * entry for the "META-INF" directory + * + * @param content the Manifest content to write to the manifest entry. + * @throws IOException + */ + protected void writeManifestEntry(JarOutputStream out, byte[] content) throws IOException { + int oldStorageMethod = storageMethod; + // Do not compress small manifest files, the compressed one is frequently + // larger than the original. The threshold of 256 bytes is somewhat arbitrary. + if (content.length < 256) { + storageMethod = JarEntry.STORED; + } + try { + writeEntry(out, MANIFEST_DIR, new byte[] {}); + writeEntry(out, MANIFEST_NAME, content); + } finally { + storageMethod = oldStorageMethod; + } + } + + /** + * Copies file or directory entries from the file system into the jar. Directory entries will be + * detected and their names automatically '/' suffixed. + */ + protected void copyEntry(JarOutputStream out, String name, Path path) throws IOException { + if (!names.contains(name)) { + if (!Files.exists(path)) { + throw new FileNotFoundException(path.toAbsolutePath() + " (No such file or directory)"); + } + boolean isDirectory = Files.isDirectory(path); + if (isDirectory && !name.endsWith("/")) { + name = name + '/'; // always normalize directory names before checking set + } + if (names.add(name)) { + if (verbose) { + System.err.println("adding " + path); + } + // Create a new entry + long size = isDirectory ? 0 : Files.size(path); + JarEntry outEntry = new JarEntry(name); + long newtime = + normalize ? normalizedTimestamp(name) : Files.getLastModifiedTime(path).toMillis(); + outEntry.setTime(newtime); + outEntry.setSize(size); + if (size == 0L) { + outEntry.setMethod(JarEntry.STORED); + outEntry.setCrc(0); + out.putNextEntry(outEntry); + } else { + outEntry.setMethod(storageMethod); + if (storageMethod == JarEntry.STORED) { + // ZipFile requires us to calculate the CRC-32 for any STORED entry. + // It would be nicer to do this via DigestInputStream, but + // the architecture of ZipOutputStream requires us to know the CRC-32 + // before we write the data to the stream. + byte[] bytes = Files.readAllBytes(path); + CRC32 crc = new CRC32(); + crc.update(bytes); + outEntry.setCrc(crc.getValue()); + out.putNextEntry(outEntry); + out.write(bytes); + } else { + out.putNextEntry(outEntry); + Files.copy(path, out); + } + } + out.closeEntry(); + } + } + } +} \ No newline at end of file From 271162cd5b2884259ed8bcca8aa89323000795f7 Mon Sep 17 00:00:00 2001 From: James Judd Date: Fri, 2 Aug 2024 18:44:53 -0600 Subject: [PATCH 2/3] Update to annex latest --- .bazelrc | 5 + WORKSPACE | 14 +- play-routes-compiler/BUILD.bazel | 1 + .../scala/CommandLinePlayRoutesCompiler.scala | 118 ++-- ...outes_compiler_cli_test_maven_install.json | 583 ++++++++---------- test/BUILD.bazel | 38 +- test/PlayForwardRoutesOnlyTest.scala | 4 +- test/PlayReverseRoutesOnlyTest.scala | 10 +- test/PlayRoutesCompilerTest.scala | 37 +- test_workspace.bzl | 12 +- 10 files changed, 413 insertions(+), 409 deletions(-) diff --git a/.bazelrc b/.bazelrc index dde1a8d..ce74d3f 100644 --- a/.bazelrc +++ b/.bazelrc @@ -4,6 +4,11 @@ common --noenable_bzlmod common:ci --color=yes +test --test_output=errors + +build --experimental_worker_multiplex_sandboxing +build --experimental_worker_cancellation + build --java_language_version="21" build --java_runtime_version="remotejdk_21" build --tool_java_language_version="21" diff --git a/WORKSPACE b/WORKSPACE index 951a0d7..eedeed7 100644 --- a/WORKSPACE +++ b/WORKSPACE @@ -89,11 +89,11 @@ load("@com_google_protobuf//:protobuf_deps.bzl", "protobuf_deps") protobuf_deps() # higherkindness/rules_scala -rules_scala_annex_version = "c8c4345e3f354753ed4ae7830618467ab59262c6" +rules_scala_annex_version = "f23c16037db66efb541dbbf5e17e6604886c85ff" http_archive( name = "rules_scala_annex", - integrity = "sha256-pmES8mOOeirB5woNYT2w97+5+C0Bt8ghrj9lHBKkMy8=", + integrity = "sha256-b/cPeh6J1Mq63u6fSWdEHAKL/kWfPhZcNL7m9If7PWM=", strip_prefix = "rules_scala-{}".format(rules_scala_annex_version), type = "zip", url = "https://github.com/lucidsoftware/rules_scala/archive/{}.zip".format(rules_scala_annex_version), @@ -154,19 +154,19 @@ load_env_vars( #################################################################### ## For tests -play_version = "2.7" # This doesn't actually matter, since we're not using the default compilers rules_play_routes provides +play_version = "3.0" # This doesn't actually matter, since we're not using the default compilers rules_play_routes provides -rules_play_routes_version = "8dbe5ee4359c30cfb7d368fed9b2df59c9665eb1" +rules_play_routes_version = "22a30c6d2d315e532b4e1963bb9e8a167c470545" http_archive( - name = "io_bazel_rules_play_routes", - sha256 = "d93e6d53440a53da4c33f78736b8b78c9a1e84623bcccd6a1cbff55e1c318c97", + name = "rules_play_routes", + sha256 = "cc9e431be031f775da1610341dd4429ff27e7c1e191f8a3018e8b39da4ca00f1", strip_prefix = "rules_play_routes-{}".format(rules_play_routes_version), type = "zip", url = "https://github.com/lucidsoftware/rules_play_routes/archive/{}.zip".format(rules_play_routes_version), ) -load("@io_bazel_rules_play_routes//:workspace.bzl", "play_routes_repositories") +load("@rules_play_routes//:workspace.bzl", "play_routes_repositories") play_routes_repositories(play_version) diff --git a/play-routes-compiler/BUILD.bazel b/play-routes-compiler/BUILD.bazel index 7e5e908..4a70286 100644 --- a/play-routes-compiler/BUILD.bazel +++ b/play-routes-compiler/BUILD.bazel @@ -17,6 +17,7 @@ scala_library( "@play_routes_compiler_cli_maven//:com_github_scopt_scopt_3", "@play_routes_compiler_cli_maven//:org_playframework_play_routes_compiler_3", "@rules_scala_annex//src/main/scala/higherkindness/rules_scala/common/error", + "@rules_scala_annex//src/main/scala/higherkindness/rules_scala/common/sandbox", "@rules_scala_annex//src/main/scala/higherkindness/rules_scala/common/worker", ], ) diff --git a/play-routes-compiler/src/main/scala/CommandLinePlayRoutesCompiler.scala b/play-routes-compiler/src/main/scala/CommandLinePlayRoutesCompiler.scala index 89f7377..3bfb6ac 100644 --- a/play-routes-compiler/src/main/scala/CommandLinePlayRoutesCompiler.scala +++ b/play-routes-compiler/src/main/scala/CommandLinePlayRoutesCompiler.scala @@ -3,74 +3,93 @@ package rulesplayroutes.routes import com.google.devtools.build.buildjar.jarhelper.JarCreator import higherkindness.rules_scala.common.error.AnnexWorkerError import higherkindness.rules_scala.common.worker.WorkerMain +import higherkindness.rules_scala.common.sandbox.SandboxUtil import java.io.{File, PrintStream} -import java.nio.file.{Files, Paths} +import java.nio.file.{Files, Path, Paths} import play.routes.compiler._ import play.routes.compiler.RoutesCompiler.RoutesCompilerTask +import scala.collection.mutable.ListBuffer import scala.jdk.CollectionConverters._ import scala.io.Source +import scala.util.{Try, Success, Failure} +import scopt.Read import scala.Console._ import scopt.OptionParser object CommandLinePlayRoutesCompiler extends WorkerMain[Unit] { + implicit val listPathRead: Read[List[Path]] = Read.reads { commaList => + commaList.split(',').view.map(Paths.get(_)).toList + } case class Config( - sources: Seq[File] = Seq.empty[File], - generatedDirectory: File = new File("."), - outputSrcJar: File = new File("."), - additionalImports: Seq[String] = Seq.empty[String], - routesGenerator: RoutesGenerator = InjectedRoutesGenerator, - generateReverseRouter: Boolean = false, - namespaceReverserRouter: Boolean = false, - generateForwardsRouter: Boolean = true + var sources: List[Path] = List.empty[Path], + var outputDirectory: Path = Paths.get("."), + var outputSrcJar: Path = Paths.get("."), + var additionalImports: List[String] = List.empty[String], + var routesGenerator: RoutesGenerator = InjectedRoutesGenerator, + var generateReverseRouter: Boolean = false, + var namespaceReverserRouter: Boolean = false, + var generateForwardsRouter: Boolean = true ) - val parser = new OptionParser[Config]("scopt") { + def parser(workDir: Path) = new OptionParser[Config]("scopt") { head("Command Line Play Routes Compiler", "0.1") - arg[File]("").required().action { (value, config) => - config.copy(generatedDirectory = value) + arg[Path]("").required().action { (outputDirectory, config) => + config.outputDirectory = SandboxUtil.getSandboxPath(workDir, outputDirectory) + config }.text("directory to output compiled routes to") - arg[File]("").required().action { (value, config) => - config.copy(outputSrcJar = value) + arg[Path]("").required().action { (outputSrcJar, config) => + config.outputSrcJar = SandboxUtil.getSandboxPath(workDir, outputSrcJar) + config }.text("file to output srcjar containing compiled routes to") - arg[Seq[File]](",...").unbounded().required().action { (value, config) => - config.copy(sources = value) + arg[List[Path]](",...").unbounded().required().action { (sources, config) => + config.sources = sources.map(SandboxUtil.getSandboxPath(workDir, _)) + config }.text("routes to compile") - opt[String]('i', "routesImport").valueName("").unbounded().action { (value, config) => - config.copy(additionalImports = config.additionalImports ++ Seq(value)) + opt[String]('i', "routesImport").valueName("").unbounded().action { (routesImport, config) => + config.additionalImports = config.additionalImports ++ List(routesImport) + config }.text("Imports for the router") - opt[String]('g', "routesGenerator").valueName("").maxOccurs(1).action { (value, config) => - config.copy(routesGenerator = { + opt[String]('g', "routesGenerator").valueName("").maxOccurs(1).action { (routesGeneratorClassString, config) => + config.routesGenerator = { try { - val name = if value.endsWith("$") then value else value + "$" + val name = if (routesGeneratorClassString.endsWith("$")) { + routesGeneratorClassString + } else { + routesGeneratorClassString + "$" + } val clazz = java.lang.Class.forName(name, true, getClass.getClassLoader) clazz.getField("MODULE$").get(null).asInstanceOf[RoutesGenerator] } catch { case e: Exception => { throw new Exception( - s"Could not instantiate a routes generator from the given class: ${value}", + s"Could not instantiate a routes generator from the given class: ${routesGeneratorClassString}", e, ) } } - }) + } + config }.text("The full class of the routes generator, e.g., play.routes.compiler.InjectedRoutesGenerator") opt[Unit]('r', "generateReverseRouter").maxOccurs(1).action { (value, config) => - config.copy(generateReverseRouter = true) + config.generateReverseRouter = true + config }.text("Whether the reverse router should be generated. Setting to false may reduce compile times if it's not needed.") opt[Unit]('n', "namespaceReverserRouter").maxOccurs(1).action { (value, config) => - config.copy(namespaceReverserRouter = true) + config.namespaceReverserRouter = true + config }.text("Whether the reverse router should be namespaced. Useful if you have many routers that use the same actions.") opt[Boolean]('f', "generateForwardsRouter").maxOccurs(1).action { (value, config) => - config.copy(generateForwardsRouter = value) + config.generateForwardsRouter = value + config }.text("Whether the forwards router should be generated. Setting this to false should allow us to only generate reverse routes for a project") } @@ -85,11 +104,11 @@ object CommandLinePlayRoutesCompiler extends WorkerMain[Unit] { /** * Do Play Routes compilation and return true if things succeeded, otherwise return false. */ - def compilePlayRoutes(config: Config): Boolean = { - config.sources.forall { file => + private def compilePlayRoutes(config: Config, out: PrintStream): Try[Unit] = Try { + config.sources.foreach { path => RoutesCompiler.compile( RoutesCompilerTask( - file, + path.toFile, config.additionalImports, config.generateForwardsRouter, config.generateReverseRouter, @@ -97,42 +116,51 @@ object CommandLinePlayRoutesCompiler extends WorkerMain[Unit] { config.namespaceReverserRouter ), config.routesGenerator, - config.generatedDirectory + config.outputDirectory.toFile(), ) match { case Right(generatedFiles) => generatedFiles.foreach { f => stripHeader(f.getPath) } - true case Left(errors) => - Console.err.println(s"${RESET}${RED}Play Routes Compilation Error:${RESET} Failed to compile routes for ${file}. Errors: ${errors}") - false + throw new Exception( + s"${RESET}${RED}Play Routes Compilation Error:${RESET} Failed to compile routes for ${path}. Errors: ${errors}" + ) } } } def generateJar(config: Config): Unit = { - val jarCreator = new JarCreator(config.outputSrcJar.toPath()) - jarCreator.addDirectory(config.generatedDirectory.toPath()) + val jarCreator = new JarCreator(config.outputSrcJar) + jarCreator.addDirectory(config.outputDirectory) jarCreator.setCompression(false) jarCreator.setNormalize(true) jarCreator.setVerbose(false) jarCreator.execute() } + /** + * Read any args passed in via files, so we can pass them to the arg parser + */ + private def readArgsFromArgFiles(args: Array[String]): List[String] = { + val builder = new ListBuffer[String]() + args.foreach { + case arg if arg.startsWith("@") => builder.addAll(Files.readAllLines(Paths.get(arg.tail)).asScala) + case arg => builder.addOne(arg) + } + builder.result() + } + override def init(args: Option[Array[String]]): Unit = () - protected def work(ctx: Unit, args: Array[String], out: PrintStream): Unit = { - val finalArgs = args.toList.flatMap { - case arg if arg.startsWith("@") => Files.readAllLines(Paths.get(arg.tail)).asScala - case arg => Array(arg) - } - val config = parser.parse(finalArgs, Config()).getOrElse(throw new AnnexWorkerError(1)) + protected def work(ctx: Unit, args: Array[String], out: PrintStream, workDir: Path, verbosity: Int): Unit = { + val config = parser(workDir).parse( + readArgsFromArgFiles(args), Config() + ).getOrElse(throw new AnnexWorkerError(1)) - if (compilePlayRoutes(config)) { - generateJar(config) - } else { - throw new AnnexWorkerError(1) + compilePlayRoutes(config, out) match { + case Success(_) => generateJar(config) + case Failure(e) => throw new AnnexWorkerError(1, "Failed to compile play routes", e) } } } \ No newline at end of file diff --git a/play_routes_compiler_cli_test_maven_install.json b/play_routes_compiler_cli_test_maven_install.json index da160ec..41a7b8c 100644 --- a/play_routes_compiler_cli_test_maven_install.json +++ b/play_routes_compiler_cli_test_maven_install.json @@ -1,11 +1,11 @@ { "__AUTOGENERATED_FILE_DO_NOT_MODIFY_THIS_FILE_MANUALLY": "THERE_IS_NO_DATA_ONLY_ZUUL", - "__INPUT_ARTIFACTS_HASH": -1874565933, - "__RESOLVED_ARTIFACTS_HASH": -810013330, + "__INPUT_ARTIFACTS_HASH": -1239612073, + "__RESOLVED_ARTIFACTS_HASH": 2007644003, "conflict_resolution": { - "org.specs2:specs2-common_2.13:4.20.3": "org.specs2:specs2-common_2.13:4.20.7", - "org.specs2:specs2-core_2.13:4.20.3": "org.specs2:specs2-core_2.13:4.20.7", - "org.specs2:specs2-matcher_2.13:4.20.3": "org.specs2:specs2-matcher_2.13:4.20.7" + "org.specs2:specs2-common_3:4.20.3": "org.specs2:specs2-common_3:4.20.7", + "org.specs2:specs2-core_3:4.20.3": "org.specs2:specs2-core_3:4.20.7", + "org.specs2:specs2-matcher_3:4.20.3": "org.specs2:specs2-matcher_3:4.20.7" }, "artifacts": { "aopalliance:aopalliance": { @@ -85,10 +85,10 @@ }, "version": "2.14.3" }, - "com.fasterxml.jackson.module:jackson-module-scala_2.13": { + "com.fasterxml.jackson.module:jackson-module-scala_3": { "shasums": { - "jar": "cbfd89031ef819ed868696206af79bf1793a31472694866f8708809f10cf86f7", - "sources": "c81ed9bb99575e23b12d844fb46e53912e6afa481fef68a3b36cf9b01cc7c1ef" + "jar": "b90e5de7dd9d3a215c448d5075a34cacf8489bbadb98ff0095d43a9dd3393aba", + "sources": "c30c481efbec70704a0aa92fc1f01f958439e228bb40f789c9d89ea580fe45c7" }, "version": "2.14.3" }, @@ -190,9 +190,9 @@ }, "version": "1.4.3" }, - "com.typesafe:ssl-config-core_2.13": { + "com.typesafe:ssl-config-core_3": { "shasums": { - "jar": "478d7a888fddc5a3f714e5ff1b665090ed9bb45cca6278c7cc94e4514a12067b", + "jar": "429b65decb3794be9430b3ff5330de61cd0a058b2345521636e698d3fd34e7e5", "sources": "d0e59959a72fc06a37d9d9fc3698de1ef89de954f52385392021148395fb9f09" }, "version": "0.6.1" @@ -409,17 +409,17 @@ }, "net.bytebuddy:byte-buddy": { "shasums": { - "jar": "e99761a526df0fefbbd3fe14436b0f953000cdfa5151dc63c0b18d37d9c46f1c", - "sources": "143dd9fe73f0566cc703934b7fd15abbb97bfab045064c2f176067e70456a136" + "jar": "94f53baeefe84c9778cd19ffb4f3d2af55eccbccac5e54a3cbf19ec17f0ede25", + "sources": "8a2e6ed855b9c83a05f09a37c02288206da65a02f55d652da0c54539814cf02d" }, - "version": "1.14.5" + "version": "1.14.8" }, "net.bytebuddy:byte-buddy-agent": { "shasums": { - "jar": "3a70240de7cdcde04e7c504c2327d7035b9c25ae0206881e3bf4e6798a273ed8", - "sources": "1e0d73101549bda70048f53fdea8b1011a97db7ddfd233ac117a221ae7f6e027" + "jar": "f7c60fd229df2b0f4e390f50e0582a23ac1d895645df0d487c54dd67a289800b", + "sources": "d7ddd0c47c810e493ffc91debe7e6737ce9b08960bb64f2712f642e8db5108f6" }, - "version": "1.12.19" + "version": "1.14.8" }, "net.sourceforge.htmlunit:htmlunit": { "shasums": { @@ -505,44 +505,44 @@ }, "version": "3.9.1" }, - "org.apache.pekko:pekko-actor-typed_2.13": { + "org.apache.pekko:pekko-actor-typed_3": { "shasums": { - "jar": "4c6606a6d595dccb5d14214813f3f37ee466d54d05b82e76d402e9539d5c981a", - "sources": "8bf983a2ab0cc5952d34592b1145369460ae6ed5b72aa04bd23b7f1251f8d699" + "jar": "4af9b5c4dc8943bb0f92aedabe5169a1baa1689b86478b84b285f5324b5b7546", + "sources": "13bd3cb99da7b076dafa8504868d835ff59750b3a3ec2f2dc4686d0bb164661f" }, "version": "1.0.2" }, - "org.apache.pekko:pekko-actor_2.13": { + "org.apache.pekko:pekko-actor_3": { "shasums": { - "jar": "52dbcb948ec4a8c3e99e777616696c4e32a77cba3d2d8f076d2b46c827233dec", - "sources": "9f22750d0853121965f835b5f6ef26d53234c648b33c4d64e0f16d2cde9fa859" + "jar": "e38a6f9948687b2cefdfc4dbf0a99bf4c0b4b81108cf842dc14786d482b93f32", + "sources": "0167d02017fc2de80fac638c2715c60118cc238dade10089032d2788fd97aa95" }, "version": "1.0.2" }, - "org.apache.pekko:pekko-protobuf-v3_2.13": { + "org.apache.pekko:pekko-protobuf-v3_3": { "shasums": { "jar": "7fb0dfbd827e7fb19443cfd5f8449e6c97d11b6705949179cf240275d67b0dd8", "sources": "e096a2c00dabdd7078c8f77ab9f5a52994e07c92c675fff4a4b2825c2dcac0da" }, "version": "1.0.2" }, - "org.apache.pekko:pekko-serialization-jackson_2.13": { + "org.apache.pekko:pekko-serialization-jackson_3": { "shasums": { - "jar": "e3c59532f41956696c5884fc6886e0d8a161490d5a0b55fde88fe346c79d02a9", + "jar": "5d7006344b354c65cb3666dc613616a5a4c03247e577966a6427003a88e20ebe", "sources": "be360b0897748217829733a27278a0eefe82ad0611f16e601870ab3db8ab4413" }, "version": "1.0.2" }, - "org.apache.pekko:pekko-slf4j_2.13": { + "org.apache.pekko:pekko-slf4j_3": { "shasums": { - "jar": "c011c8e454f7cfd002fe70b74ab74705b21b3b4cb6171f4b687ce2bb6dc925b8", + "jar": "a3383b3ec3523693b44ad7598e3c39d91b357c1e66cd6063e32e456bb0c53aaa", "sources": "7ea4ad9a7f5e42f987ee9f4c08e7af1f7bb7632ad2deab3e7cd958502c0c1498" }, "version": "1.0.2" }, - "org.apache.pekko:pekko-stream_2.13": { + "org.apache.pekko:pekko-stream_3": { "shasums": { - "jar": "47b4e8dd133561b2fee37455ffdd3885830dc444dbd1ed5724548451ac160731", + "jar": "992896d35678ce1cc6fc17540b4a7ad7866cf346e4fc6b16b3b236b75af034ab", "sources": "84f2bb1d1b37f708ea4b173aed9a081a9ca63166e9715ed79e5f56dc113cb2e4" }, "version": "1.0.2" @@ -624,13 +624,6 @@ }, "version": "9.4.50.v20221201" }, - "org.hamcrest:hamcrest": { - "shasums": { - "jar": "5e62846a89f05cd78cd9c1a553f340d002458380c320455dd1f8fc5497a8a1c1", - "sources": "f49e697dbc70591f91a90dd7f741f5780f53f63f34a416d6a9879499d4d666af" - }, - "version": "2.2" - }, "org.hamcrest:hamcrest-core": { "shasums": { "jar": "66fdef91e9739348df7a096aa384a5685f4e875584cce89386a7a47251c4d8e9", @@ -647,10 +640,10 @@ }, "org.mockito:mockito-core": { "shasums": { - "jar": "4b909690cab288c761eb94c0bf0e814496cf3921d8affac84cd87774530351e5", - "sources": "34741d9f2cceb187358f5a3195de179467ca876c9a0540ad0ef3d14e3a7c78bf" + "jar": "aaf9aabadf375eb2755b5aab685f14e5c74268c657cb95c0cc7badbd665d9cda", + "sources": "0a42c1a87adaa4271dcf9cf545c9c78f1a2f0e8b90a1c410b6c419e3e1d99f51" }, - "version": "4.11.0" + "version": "5.6.0" }, "org.objenesis:objenesis": { "shasums": { @@ -666,10 +659,10 @@ }, "version": "7.1" }, - "org.playframework.twirl:twirl-api_2.13": { + "org.playframework.twirl:twirl-api_3": { "shasums": { - "jar": "83ec112fd255753e406f074bd126e8970f0ccc9c4155103aa66480e6b9a90319", - "sources": "ae2f3697b0767718aa982d5c22119cc76993b5d1c67ec6ff2f33ae9b10ea9ef7" + "jar": "550e4b0b2ef22d22124a1f83b8f6b1b12c3643707b9d32354af5760aa6f696fc", + "sources": "4505baa19a38c5fe3498a42c7a56d0fb833176debd064e4385ef2cd6800e22df" }, "version": "2.0.6" }, @@ -680,9 +673,9 @@ }, "version": "3.0.4" }, - "org.playframework:play-configuration_2.13": { + "org.playframework:play-configuration_3": { "shasums": { - "jar": "8fc074a2f25ee9b543af695f129fb14f02189f7c19a11e26e90e62a78cbb3920", + "jar": "a59f01ddeadf4ef81e039700dfa9c154fc73d5c8fdc7be651634d8075b6a2193", "sources": "e403f1f020f95899e8d8d493c2d3563dcf22df0dfd3b3dcacc017d41b654dd81" }, "version": "3.0.4" @@ -694,59 +687,59 @@ }, "version": "3.0.4" }, - "org.playframework:play-functional_2.13": { + "org.playframework:play-functional_3": { "shasums": { - "jar": "f4276485f91c4fedf73426740ace21b660c0b9dd2fccfabe6c4e5aa14e1481f5", + "jar": "a0ff6d625cb7066a3e559148751e6d5822b76847008e544fceddac29a63ccf3e", "sources": "130056318d90cadcbb1c8bd65c188963a9d20a302d71b168460d2c7deb54a972" }, "version": "3.0.4" }, - "org.playframework:play-guice_2.13": { + "org.playframework:play-guice_3": { "shasums": { - "jar": "50674e2e5a5e3c7a0e909ff5bf8d30118fd5ecd4b9a4ccd02d06fb6cf0d0a983", + "jar": "a82ad83337c53784cce38c9317e12fa52f777e08a3022a437fe1807f17ab09a2", "sources": "6be0e0b0214968a87d86b8eb678feb7e1aa86e28c02d5d450232d5fbcc35f96c" }, "version": "3.0.4" }, - "org.playframework:play-json_2.13": { + "org.playframework:play-json_3": { "shasums": { - "jar": "baa58ddbd4be07b7601f05be574d50ecbc83a090ce8afedda74797d0f69f610a", - "sources": "c397b0c0c4b070595ea062b63248bea45c6df9976670e242a3ba6de6a4b8f845" + "jar": "cccc992d104f5694798ee5391d29758ba59e374d1edc82a43cd9f3bdcc57764a", + "sources": "b8eec5e983e866af339aea1aca4d2104fcfa47e90daadfff99409f8509b804fb" }, "version": "3.0.4" }, - "org.playframework:play-server_2.13": { + "org.playframework:play-server_3": { "shasums": { - "jar": "fff13ed9ad711b0bc94d7d6e878c0f649c12b38264a1924bf1dd4ea2b4c1409c", + "jar": "ad0a962c08fd948e469d2e146f167d994d6181109edcfc8f941220596ae34002", "sources": "88331a786fbd0929a06234d4998549665bce5c4b7705798e6f87354dd0b512ba" }, "version": "3.0.4" }, - "org.playframework:play-specs2_2.13": { + "org.playframework:play-specs2_3": { "shasums": { - "jar": "9642a542dfb20f25007f098631e357dec56f564fc6d0cb07f1adbe80cdc29fbb", + "jar": "252b9110c39a242f683442280b71398b394b8d01f308e4d0237735e507f2e8a3", "sources": "b7cdf363db85311810eda05027685e319ebfbea7214c44c84d6bfa7ce83f8123" }, "version": "3.0.4" }, - "org.playframework:play-streams_2.13": { + "org.playframework:play-streams_3": { "shasums": { - "jar": "ae2ad38523f1144594b3290432ae689bfc231f9f04fb649bd1cf8084f69aa3a1", + "jar": "03799cbaf0d7e5ae0e799b467378190d63606c41e21c621ecfb8fafdcd833392", "sources": "1eec54ddc52d96d0a8889bd5ee2cd4f68b1372043affc7a820769a26bc3cf55b" }, "version": "3.0.4" }, - "org.playframework:play-test_2.13": { + "org.playframework:play-test_3": { "shasums": { - "jar": "c9045152b34b6af9322fb2e9bae0b7244279edc3cefcf883790bde00350b2d65", + "jar": "2e3ae91bc88db1816bdc41baa59eac3514d31f4f15bee61562fd3f5f48b89353", "sources": "0a1fcd4734f8628ca853d9ef2b049164c069c69770d863c694f8da125a80f035" }, "version": "3.0.4" }, - "org.playframework:play_2.13": { + "org.playframework:play_3": { "shasums": { - "jar": "59ab25025e31f1778311ea27f943fb7de8cc8a8d8392361b794fea95b940c9fa", - "sources": "3cfa86a3d7b4316aefbaf865b819a0fce87467af72e73fd32cb5492ff63ecf88" + "jar": "4750a911c7b465fbbbd6303a9b9e393a1a0a791de706b6494c875ceef6f21fe3", + "sources": "c3cf5bea4f18b87eb7bc2fe80595afcd2686d4d552fa1e6677d3094ea7b06659" }, "version": "3.0.4" }, @@ -764,33 +757,33 @@ }, "version": "1.0.4" }, - "org.scala-lang.modules:scala-parser-combinators_2.13": { + "org.scala-lang.modules:scala-parser-combinators_3": { "shasums": { - "jar": "5c285b72e6dc0a98e99ae0a1ceeb4027dab9adfa441844046bd3f19e0efdcb54", - "sources": "a5cdd33bc2dcd8917e4fea30d31ea19d0d70cc5f6951c5a913428930ced8391a" + "jar": "c3d4e8de5d2ce71d70d5d227b54714a50b32a1edf2d4be0a9fdbe88cdcd44b48", + "sources": "57890ac2e087209d1e7bdba49f3f78fada9e254c4a3c43b9c5afb10405ecf3ab" }, - "version": "1.1.2" + "version": "2.3.0" }, - "org.scala-lang.modules:scala-xml_2.13": { + "org.scala-lang.modules:scala-xml_3": { "shasums": { - "jar": "0d9d63091a73cf837cd5412671a30abecad460dc254aeb43a2b18f4910af6a09", - "sources": "75edeab4d6688246d26a8de2deb430bc65a46dd25eb0350b3872c8631a9de602" + "jar": "3220723238102107ab83182468e5dbe351b081a0601386710ef46c81a95d38d0", + "sources": "d76b5646ed58104dfbc9705d70031c35b3aad49c23f652e9d83a45398e9292f2" }, - "version": "2.2.0" + "version": "2.3.0" }, "org.scala-lang:scala-library": { "shasums": { - "jar": "43e0ca1583df1966eaf02f0fbddcfb3784b995dd06bfc907209347758ce4b7e3", - "sources": "4be0650f427ebf6ff8a462fe634fdc02665d59ec3962c4d98dbf5ac766f1dd4f" + "jar": "c6a879e4973a60f6162668542a33eaccc2bb565d1c934fb061c5844259131dd1", + "sources": "df3f19e71b4d2dd6bb882a6deafb31c7dceaad4f26489b9fd9ca56b493229174" }, - "version": "2.13.14" + "version": "2.13.12" }, - "org.scala-lang:scala-reflect": { + "org.scala-lang:scala3-library_3": { "shasums": { - "jar": "8846baaa8cf43b1b19725ab737abff145ca58d14a4d02e75d71ca8f7ca5f2926", - "sources": "94bf451e612d9460dbc7cee4beed84a7e5dd7b86bcb901ee8c78f7cf5e035e01" + "jar": "16fe064f1373ed6f098d3d9f812a398ed5075db4bf2721c04e630502cb352816", + "sources": "8ad889e79b1e8c393dc7e03ae2b510d280bea4561c2e35c0948919bd9724e757" }, - "version": "2.13.14" + "version": "3.3.3" }, "org.scala-sbt:test-interface": { "shasums": { @@ -890,45 +883,38 @@ }, "version": "2.0.13" }, - "org.specs2:specs2-common_2.13": { - "shasums": { - "jar": "ff0c47caa835d516bdfbdb8fdf3598df607f6a3a0c261fb3f46fde024f927e9c", - "sources": "a86cec9286fdf424e57ab66c060251ff15f7879d4b5a10a0329630826dfd7c99" - }, - "version": "4.20.7" - }, - "org.specs2:specs2-core_2.13": { + "org.specs2:specs2-common_3": { "shasums": { - "jar": "ebd955c02e8c00c1eefc0827d6053d2acdd9082794df6408b611e8ad7b0786fe", - "sources": "160c6c632cb6442ca94fc7527af4e0671f691abdd29e81b042d57df2eaf1f98e" + "jar": "3b119a94d6b16c8a5f917afd16013d3ac343c1ed978bea2c52a203271cd557a7", + "sources": "5046ed3e8b4f11fbe6225c25bdd5869a0b997e70fdde4315266a90fb536f01c3" }, "version": "4.20.7" }, - "org.specs2:specs2-fp_2.13": { + "org.specs2:specs2-core_3": { "shasums": { - "jar": "2e63eec87f7be7bf89546e8726a655cd2a7d4c6cd6c4324f7c4ca290ed3abb95", - "sources": "37bb6311912925e97aa145b167a6da46a2a6015a7835863a46c957dd573f4dbf" + "jar": "cf226bbbba40375853dc001e0f55312eb385805f054f7e9f8bc35b54c6ce6439", + "sources": "ee983d2a746cc22927ebf5dddf7c7cfda96f556f239fc0e7e11bec5cfba22974" }, "version": "4.20.7" }, - "org.specs2:specs2-junit_2.13": { + "org.specs2:specs2-fp_3": { "shasums": { - "jar": "ab5fc76f54904219b498732db4ad5bc000925044a5527eff4fb7aa3903524f0e", - "sources": "371c48efaad174e8197b0dd8bd838134a002716491b9b639409de29cf2c7f43c" + "jar": "6495e55bee81037ced9fa0bd5617fcab59e5efeca367ad665cd984da69f95023", + "sources": "58296724d1d3e8a370dc51cee517eb58e18e5a3597a62c64d6e90553b472633b" }, "version": "4.20.7" }, - "org.specs2:specs2-matcher_2.13": { + "org.specs2:specs2-junit_3": { "shasums": { - "jar": "73f340a770670f7828ee8e1c567d1d64228035b192e07362567cffa6c0026538", - "sources": "f7dda7977b48c77ac4c20fbad448674e946d867768d009ef4aa5db0ff436ac0e" + "jar": "5ca54267d0925c48a16b6e9f00d17e76a06476d670d4ba978b6a70efd103c756", + "sources": "28f2c6e7eb9b8297f79939e7f7f429ba4e0ac910babf7dba42a45f115d0b5fc7" }, "version": "4.20.7" }, - "org.specs2:specs2-mock_2.13": { + "org.specs2:specs2-matcher_3": { "shasums": { - "jar": "d5826b05370ba8535653035d908f8503549dd09ac6f63577862b428596fd5be8", - "sources": "24b187817fbf27e36bd85e89e1e7865553a424acb344f7c9871a1bafc048d57d" + "jar": "27de3c622baa78f1388a7601d9c51daf7ce15de70d87ec5beacb6a655c972fd7", + "sources": "84484798e83b2c34ffe3942ded0cbfc031f0e3e9024c191dddb2545fc9ef5c22" }, "version": "4.20.7" } @@ -962,12 +948,12 @@ "com.fasterxml.jackson.core:jackson-core", "com.fasterxml.jackson.core:jackson-databind" ], - "com.fasterxml.jackson.module:jackson-module-scala_2.13": [ + "com.fasterxml.jackson.module:jackson-module-scala_3": [ "com.fasterxml.jackson.core:jackson-annotations", "com.fasterxml.jackson.core:jackson-core", "com.fasterxml.jackson.core:jackson-databind", "com.thoughtworks.paranamer:paranamer", - "org.scala-lang:scala-library" + "org.scala-lang:scala3-library_3" ], "com.github.sbt:junit-interface": [ "junit:junit", @@ -991,9 +977,9 @@ "jakarta.inject:jakarta.inject-api", "javax.inject:javax.inject" ], - "com.typesafe:ssl-config-core_2.13": [ + "com.typesafe:ssl-config-core_3": [ "com.typesafe:config", - "org.scala-lang:scala-library" + "org.scala-lang:scala3-library_3" ], "commons-beanutils:commons-beanutils": [ "commons-collections:commons-collections", @@ -1117,17 +1103,17 @@ "org.apache.maven:maven-model": [ "org.codehaus.plexus:plexus-utils" ], - "org.apache.pekko:pekko-actor-typed_2.13": [ - "org.apache.pekko:pekko-actor_2.13", - "org.apache.pekko:pekko-slf4j_2.13", - "org.scala-lang:scala-library", + "org.apache.pekko:pekko-actor-typed_3": [ + "org.apache.pekko:pekko-actor_3", + "org.apache.pekko:pekko-slf4j_3", + "org.scala-lang:scala3-library_3", "org.slf4j:slf4j-api" ], - "org.apache.pekko:pekko-actor_2.13": [ + "org.apache.pekko:pekko-actor_3": [ "com.typesafe:config", - "org.scala-lang:scala-library" + "org.scala-lang:scala3-library_3" ], - "org.apache.pekko:pekko-serialization-jackson_2.13": [ + "org.apache.pekko:pekko-serialization-jackson_3": [ "com.fasterxml.jackson.core:jackson-annotations", "com.fasterxml.jackson.core:jackson-core", "com.fasterxml.jackson.core:jackson-databind", @@ -1135,22 +1121,22 @@ "com.fasterxml.jackson.datatype:jackson-datatype-jdk8", "com.fasterxml.jackson.datatype:jackson-datatype-jsr310", "com.fasterxml.jackson.module:jackson-module-parameter-names", - "com.fasterxml.jackson.module:jackson-module-scala_2.13", - "org.apache.pekko:pekko-actor_2.13", + "com.fasterxml.jackson.module:jackson-module-scala_3", + "org.apache.pekko:pekko-actor_3", "org.lz4:lz4-java", - "org.scala-lang:scala-library" + "org.scala-lang:scala3-library_3" ], - "org.apache.pekko:pekko-slf4j_2.13": [ - "org.apache.pekko:pekko-actor_2.13", - "org.scala-lang:scala-library", + "org.apache.pekko:pekko-slf4j_3": [ + "org.apache.pekko:pekko-actor_3", + "org.scala-lang:scala3-library_3", "org.slf4j:slf4j-api" ], - "org.apache.pekko:pekko-stream_2.13": [ - "com.typesafe:ssl-config-core_2.13", - "org.apache.pekko:pekko-actor_2.13", - "org.apache.pekko:pekko-protobuf-v3_2.13", + "org.apache.pekko:pekko-stream_3": [ + "com.typesafe:ssl-config-core_3", + "org.apache.pekko:pekko-actor_3", + "org.apache.pekko:pekko-protobuf-v3_3", "org.reactivestreams:reactive-streams", - "org.scala-lang:scala-library" + "org.scala-lang:scala3-library_3" ], "org.eclipse.jetty.websocket:websocket-client": [ "org.eclipse.jetty.websocket:websocket-common", @@ -1179,55 +1165,54 @@ "net.bytebuddy:byte-buddy-agent", "org.objenesis:objenesis" ], - "org.playframework.twirl:twirl-api_2.13": [ - "org.scala-lang.modules:scala-xml_2.13", - "org.scala-lang:scala-library" + "org.playframework.twirl:twirl-api_3": [ + "org.scala-lang.modules:scala-xml_3", + "org.scala-lang:scala3-library_3" ], "org.playframework:play-build-link": [ "org.playframework:play-exceptions" ], - "org.playframework:play-configuration_2.13": [ + "org.playframework:play-configuration_3": [ "com.typesafe:config", "org.playframework:play-exceptions", - "org.scala-lang:scala-library", + "org.scala-lang:scala3-library_3", "org.slf4j:slf4j-api" ], - "org.playframework:play-functional_2.13": [ - "org.scala-lang:scala-library" + "org.playframework:play-functional_3": [ + "org.scala-lang:scala3-library_3" ], - "org.playframework:play-guice_2.13": [ + "org.playframework:play-guice_3": [ "com.google.inject.extensions:guice-assistedinject", "com.google.inject:guice", - "org.playframework:play_2.13", - "org.scala-lang:scala-library" + "org.playframework:play_3", + "org.scala-lang:scala3-library_3" ], - "org.playframework:play-json_2.13": [ + "org.playframework:play-json_3": [ "com.fasterxml.jackson.core:jackson-annotations", "com.fasterxml.jackson.core:jackson-core", "com.fasterxml.jackson.core:jackson-databind", "com.fasterxml.jackson.datatype:jackson-datatype-jdk8", "com.fasterxml.jackson.datatype:jackson-datatype-jsr310", - "org.playframework:play-functional_2.13", - "org.scala-lang:scala-library", - "org.scala-lang:scala-reflect" + "org.playframework:play-functional_3", + "org.scala-lang:scala3-library_3" ], - "org.playframework:play-server_2.13": [ - "org.playframework:play_2.13", - "org.scala-lang:scala-library" + "org.playframework:play-server_3": [ + "org.playframework:play_3", + "org.scala-lang:scala3-library_3" ], - "org.playframework:play-specs2_2.13": [ - "org.playframework:play-test_2.13", - "org.scala-lang:scala-library", - "org.specs2:specs2-core_2.13", - "org.specs2:specs2-junit_2.13", - "org.specs2:specs2-mock_2.13" + "org.playframework:play-specs2_3": [ + "org.mockito:mockito-core", + "org.playframework:play-test_3", + "org.scala-lang:scala3-library_3", + "org.specs2:specs2-core_3", + "org.specs2:specs2-junit_3" ], - "org.playframework:play-streams_2.13": [ - "org.apache.pekko:pekko-stream_2.13", + "org.playframework:play-streams_3": [ + "org.apache.pekko:pekko-stream_3", "org.reactivestreams:reactive-streams", - "org.scala-lang:scala-library" + "org.scala-lang:scala3-library_3" ], - "org.playframework:play-test_2.13": [ + "org.playframework:play-test_3": [ "ch.qos.logback:logback-classic", "com.github.sbt:junit-interface", "com.google.guava:guava", @@ -1235,15 +1220,15 @@ "com.google.inject:guice", "io.fluentlenium:fluentlenium-core", "junit:junit", - "org.playframework:play-guice_2.13", - "org.playframework:play-server_2.13", - "org.scala-lang:scala-library", + "org.playframework:play-guice_3", + "org.playframework:play-server_3", + "org.scala-lang:scala3-library_3", "org.seleniumhq.selenium:htmlunit-driver", "org.seleniumhq.selenium:selenium-api", "org.seleniumhq.selenium:selenium-firefox-driver", "org.seleniumhq.selenium:selenium-support" ], - "org.playframework:play_2.13": [ + "org.playframework:play_3": [ "com.fasterxml.jackson.core:jackson-annotations", "com.fasterxml.jackson.core:jackson-core", "com.fasterxml.jackson.core:jackson-databind", @@ -1251,24 +1236,24 @@ "com.fasterxml.jackson.datatype:jackson-datatype-jdk8", "com.fasterxml.jackson.datatype:jackson-datatype-jsr310", "com.fasterxml.jackson.module:jackson-module-parameter-names", - "com.fasterxml.jackson.module:jackson-module-scala_2.13", + "com.fasterxml.jackson.module:jackson-module-scala_3", "com.google.guava:guava", - "com.typesafe:ssl-config-core_2.13", + "com.typesafe:ssl-config-core_3", "io.jsonwebtoken:jjwt-api", "io.jsonwebtoken:jjwt-impl", "io.jsonwebtoken:jjwt-jackson", "javax.inject:javax.inject", - "org.apache.pekko:pekko-actor-typed_2.13", - "org.apache.pekko:pekko-actor_2.13", - "org.apache.pekko:pekko-serialization-jackson_2.13", - "org.apache.pekko:pekko-slf4j_2.13", - "org.playframework.twirl:twirl-api_2.13", + "org.apache.pekko:pekko-actor-typed_3", + "org.apache.pekko:pekko-actor_3", + "org.apache.pekko:pekko-serialization-jackson_3", + "org.apache.pekko:pekko-slf4j_3", + "org.playframework.twirl:twirl-api_3", "org.playframework:play-build-link", - "org.playframework:play-configuration_2.13", - "org.playframework:play-json_2.13", - "org.playframework:play-streams_2.13", - "org.scala-lang.modules:scala-parser-combinators_2.13", - "org.scala-lang:scala-library", + "org.playframework:play-configuration_3", + "org.playframework:play-json_3", + "org.playframework:play-streams_3", + "org.scala-lang.modules:scala-parser-combinators_3", + "org.scala-lang:scala3-library_3", "org.slf4j:jcl-over-slf4j", "org.slf4j:jul-to-slf4j", "org.slf4j:slf4j-api" @@ -1276,13 +1261,13 @@ "org.portable-scala:portable-scala-reflect_2.13": [ "org.scala-lang:scala-library" ], - "org.scala-lang.modules:scala-parser-combinators_2.13": [ - "org.scala-lang:scala-library" + "org.scala-lang.modules:scala-parser-combinators_3": [ + "org.scala-lang:scala3-library_3" ], - "org.scala-lang.modules:scala-xml_2.13": [ - "org.scala-lang:scala-library" + "org.scala-lang.modules:scala-xml_3": [ + "org.scala-lang:scala3-library_3" ], - "org.scala-lang:scala-reflect": [ + "org.scala-lang:scala3-library_3": [ "org.scala-lang:scala-library" ], "org.seleniumhq.selenium:htmlunit-driver": [ @@ -1358,43 +1343,33 @@ "org.slf4j:jul-to-slf4j": [ "org.slf4j:slf4j-api" ], - "org.specs2:specs2-common_2.13": [ + "org.specs2:specs2-common_3": [ "org.portable-scala:portable-scala-reflect_2.13", - "org.scala-lang.modules:scala-parser-combinators_2.13", - "org.scala-lang:scala-library", - "org.scala-lang:scala-reflect", + "org.scala-lang:scala3-library_3", "org.scala-sbt:test-interface", - "org.specs2:specs2-fp_2.13" + "org.specs2:specs2-fp_3" ], - "org.specs2:specs2-core_2.13": [ + "org.specs2:specs2-core_3": [ "org.portable-scala:portable-scala-reflect_2.13", - "org.scala-lang:scala-library", + "org.scala-lang:scala3-library_3", "org.scala-sbt:test-interface", - "org.specs2:specs2-common_2.13", - "org.specs2:specs2-matcher_2.13" + "org.specs2:specs2-common_3", + "org.specs2:specs2-matcher_3" ], - "org.specs2:specs2-fp_2.13": [ - "org.scala-lang:scala-library" + "org.specs2:specs2-fp_3": [ + "org.scala-lang:scala3-library_3" ], - "org.specs2:specs2-junit_2.13": [ + "org.specs2:specs2-junit_3": [ "junit:junit", "org.portable-scala:portable-scala-reflect_2.13", - "org.scala-lang.modules:scala-xml_2.13", - "org.scala-lang:scala-library", + "org.scala-lang.modules:scala-xml_3", + "org.scala-lang:scala3-library_3", "org.scala-sbt:test-interface", - "org.specs2:specs2-core_2.13" - ], - "org.specs2:specs2-matcher_2.13": [ - "org.scala-lang:scala-library", - "org.specs2:specs2-common_2.13" + "org.specs2:specs2-core_3" ], - "org.specs2:specs2-mock_2.13": [ - "org.hamcrest:hamcrest", - "org.mockito:mockito-core", - "org.portable-scala:portable-scala-reflect_2.13", - "org.scala-lang:scala-library", - "org.scala-sbt:test-interface", - "org.specs2:specs2-core_2.13" + "org.specs2:specs2-matcher_3": [ + "org.scala-lang:scala3-library_3", + "org.specs2:specs2-common_3" ] }, "packages": { @@ -1547,7 +1522,7 @@ "com.fasterxml.jackson.module:jackson-module-parameter-names": [ "com.fasterxml.jackson.module.paramnames" ], - "com.fasterxml.jackson.module:jackson-module-scala_2.13": [ + "com.fasterxml.jackson.module:jackson-module-scala_3": [ "com.fasterxml.jackson.module.scala", "com.fasterxml.jackson.module.scala.deser", "com.fasterxml.jackson.module.scala.experimental", @@ -1639,7 +1614,7 @@ "com.typesafe.config.impl", "com.typesafe.config.parser" ], - "com.typesafe:ssl-config-core_2.13": [ + "com.typesafe:ssl-config-core_3": [ "com.typesafe.sslconfig.ssl", "com.typesafe.sslconfig.ssl.debug", "com.typesafe.sslconfig.ssl.tracing", @@ -2238,7 +2213,7 @@ "org.apache.maven.model.io.xpp3", "org.apache.maven.model.merge" ], - "org.apache.pekko:pekko-actor-typed_2.13": [ + "org.apache.pekko:pekko-actor-typed_3": [ "org.apache.pekko.actor.typed", "org.apache.pekko.actor.typed.delivery", "org.apache.pekko.actor.typed.delivery.internal", @@ -2255,7 +2230,7 @@ "org.apache.pekko.actor.typed.scaladsl", "org.apache.pekko.actor.typed.scaladsl.adapter" ], - "org.apache.pekko:pekko-actor_2.13": [ + "org.apache.pekko:pekko-actor_3": [ "org.apache.pekko", "org.apache.pekko.actor", "org.apache.pekko.actor.dungeon", @@ -2284,17 +2259,17 @@ "org.apache.pekko.util", "org.apache.pekko.util.ccompat" ], - "org.apache.pekko:pekko-protobuf-v3_2.13": [ + "org.apache.pekko:pekko-protobuf-v3_3": [ "org.apache.pekko.protobufv3.internal", "org.apache.pekko.protobufv3.internal.compiler" ], - "org.apache.pekko:pekko-serialization-jackson_2.13": [ + "org.apache.pekko:pekko-serialization-jackson_3": [ "org.apache.pekko.serialization.jackson" ], - "org.apache.pekko:pekko-slf4j_2.13": [ + "org.apache.pekko:pekko-slf4j_3": [ "org.apache.pekko.event.slf4j" ], - "org.apache.pekko:pekko-stream_2.13": [ + "org.apache.pekko:pekko-stream_3": [ "com.typesafe.sslconfig.pekko", "com.typesafe.sslconfig.pekko.util", "org.apache.pekko.stream", @@ -2417,19 +2392,6 @@ "org.eclipse.jetty.util.thread", "org.eclipse.jetty.util.thread.strategy" ], - "org.hamcrest:hamcrest": [ - "org.hamcrest", - "org.hamcrest.beans", - "org.hamcrest.collection", - "org.hamcrest.comparator", - "org.hamcrest.core", - "org.hamcrest.internal", - "org.hamcrest.io", - "org.hamcrest.number", - "org.hamcrest.object", - "org.hamcrest.text", - "org.hamcrest.xml" - ], "org.hamcrest:hamcrest-core": [ "org.hamcrest", "org.hamcrest.core", @@ -2522,7 +2484,7 @@ "org.objectweb.asm", "org.objectweb.asm.signature" ], - "org.playframework.twirl:twirl-api_2.13": [ + "org.playframework.twirl:twirl-api_3": [ "play.twirl.api", "play.twirl.api.utils" ], @@ -2531,47 +2493,47 @@ "play.core", "play.core.server" ], - "org.playframework:play-configuration_2.13": [ + "org.playframework:play-configuration_3": [ "play", "play.api" ], "org.playframework:play-exceptions": [ "play.api" ], - "org.playframework:play-functional_2.13": [ + "org.playframework:play-functional_3": [ "play.api.libs.functional", "play.api.libs.functional.syntax" ], - "org.playframework:play-guice_2.13": [ + "org.playframework:play-guice_3": [ "play.api.inject.guice", "play.api.libs.concurrent", "play.inject.guice", "play.libs.pekko" ], - "org.playframework:play-json_2.13": [ + "org.playframework:play-json_3": [ "play.api.libs.json", "play.api.libs.json.jackson", "play.api.libs.json.util" ], - "org.playframework:play-server_2.13": [ + "org.playframework:play-server_3": [ "play.core.server", "play.core.server.common", "play.core.server.ssl", "play.server" ], - "org.playframework:play-specs2_2.13": [ + "org.playframework:play-specs2_3": [ "play.api.test" ], - "org.playframework:play-streams_2.13": [ + "org.playframework:play-streams_3": [ "play.api.libs.streams", "play.libs.streams" ], - "org.playframework:play-test_2.13": [ + "org.playframework:play-test_3": [ "org.apache.pekko.stream.testkit", "play.api.test", "play.test" ], - "org.playframework:play_2.13": [ + "org.playframework:play_3": [ "controllers", "models", "play", @@ -2640,15 +2602,14 @@ "org.reactivestreams:reactive-streams": [ "org.reactivestreams" ], - "org.scala-lang.modules:scala-parser-combinators_2.13": [ + "org.scala-lang.modules:scala-parser-combinators_3": [ "scala.util.parsing.combinator", "scala.util.parsing.combinator.lexical", "scala.util.parsing.combinator.syntactical", "scala.util.parsing.combinator.token", - "scala.util.parsing.input", - "scala.util.parsing.json" + "scala.util.parsing.input" ], - "org.scala-lang.modules:scala-xml_2.13": [ + "org.scala-lang.modules:scala-xml_3": [ "scala.xml", "scala.xml.dtd", "scala.xml.dtd.impl", @@ -2691,20 +2652,24 @@ "scala.util.hashing", "scala.util.matching" ], - "org.scala-lang:scala-reflect": [ - "scala.reflect.api", - "scala.reflect.internal", - "scala.reflect.internal.annotations", - "scala.reflect.internal.pickling", - "scala.reflect.internal.settings", - "scala.reflect.internal.tpe", - "scala.reflect.internal.transform", - "scala.reflect.internal.util", - "scala.reflect.io", - "scala.reflect.macros", - "scala.reflect.macros.blackbox", - "scala.reflect.macros.whitebox", - "scala.reflect.runtime" + "org.scala-lang:scala3-library_3": [ + "scala", + "scala.annotation", + "scala.annotation.internal", + "scala.annotation.unchecked", + "scala.compiletime", + "scala.compiletime.ops", + "scala.compiletime.testing", + "scala.deriving", + "scala.quoted", + "scala.quoted.runtime", + "scala.reflect", + "scala.runtime", + "scala.runtime.coverage", + "scala.runtime.function", + "scala.runtime.stdLibPatches", + "scala.util", + "scala.util.control" ], "org.scala-sbt:test-interface": [ "org.scalatools.testing", @@ -2885,7 +2850,7 @@ "org.slf4j.helpers", "org.slf4j.spi" ], - "org.specs2:specs2-common_2.13": [ + "org.specs2:specs2-common_3": [ "org.specs2", "org.specs2.collection", "org.specs2.concurrent", @@ -2903,7 +2868,7 @@ "org.specs2.time", "specs2" ], - "org.specs2:specs2-core_2.13": [ + "org.specs2:specs2-core_3": [ "org.specs2", "org.specs2.control", "org.specs2.execute", @@ -2925,27 +2890,19 @@ "org.specs2.specification.script", "specs2" ], - "org.specs2:specs2-fp_2.13": [ + "org.specs2:specs2-fp_3": [ "org.specs2.fp" ], - "org.specs2:specs2-junit_2.13": [ + "org.specs2:specs2-junit_3": [ "org.specs2", "org.specs2.matcher", "org.specs2.mutable", "org.specs2.reporter", "org.specs2.runner" ], - "org.specs2:specs2-matcher_2.13": [ + "org.specs2:specs2-matcher_3": [ "org.specs2.matcher", "org.specs2.matcher.describe" - ], - "org.specs2:specs2-mock_2.13": [ - "org.mockito.internal.invocation", - "org.mockito.internal.matchers", - "org.mockito.internal.progress", - "org.specs2.matcher", - "org.specs2.mock", - "org.specs2.mock.mockito" ] }, "repositories": { @@ -2972,8 +2929,8 @@ "com.fasterxml.jackson.datatype:jackson-datatype-jsr310:jar:sources", "com.fasterxml.jackson.module:jackson-module-parameter-names", "com.fasterxml.jackson.module:jackson-module-parameter-names:jar:sources", - "com.fasterxml.jackson.module:jackson-module-scala_2.13", - "com.fasterxml.jackson.module:jackson-module-scala_2.13:jar:sources", + "com.fasterxml.jackson.module:jackson-module-scala_3", + "com.fasterxml.jackson.module:jackson-module-scala_3:jar:sources", "com.github.sbt:junit-interface", "com.github.sbt:junit-interface:jar:sources", "com.google.auto.service:auto-service-annotations", @@ -3001,8 +2958,8 @@ "com.thoughtworks.paranamer:paranamer:jar:sources", "com.typesafe:config", "com.typesafe:config:jar:sources", - "com.typesafe:ssl-config-core_2.13", - "com.typesafe:ssl-config-core_2.13:jar:sources", + "com.typesafe:ssl-config-core_3", + "com.typesafe:ssl-config-core_3:jar:sources", "commons-beanutils:commons-beanutils", "commons-beanutils:commons-beanutils:jar:sources", "commons-codec:commons-codec", @@ -3091,18 +3048,18 @@ "org.apache.httpcomponents:httpmime:jar:sources", "org.apache.maven:maven-model", "org.apache.maven:maven-model:jar:sources", - "org.apache.pekko:pekko-actor-typed_2.13", - "org.apache.pekko:pekko-actor-typed_2.13:jar:sources", - "org.apache.pekko:pekko-actor_2.13", - "org.apache.pekko:pekko-actor_2.13:jar:sources", - "org.apache.pekko:pekko-protobuf-v3_2.13", - "org.apache.pekko:pekko-protobuf-v3_2.13:jar:sources", - "org.apache.pekko:pekko-serialization-jackson_2.13", - "org.apache.pekko:pekko-serialization-jackson_2.13:jar:sources", - "org.apache.pekko:pekko-slf4j_2.13", - "org.apache.pekko:pekko-slf4j_2.13:jar:sources", - "org.apache.pekko:pekko-stream_2.13", - "org.apache.pekko:pekko-stream_2.13:jar:sources", + "org.apache.pekko:pekko-actor-typed_3", + "org.apache.pekko:pekko-actor-typed_3:jar:sources", + "org.apache.pekko:pekko-actor_3", + "org.apache.pekko:pekko-actor_3:jar:sources", + "org.apache.pekko:pekko-protobuf-v3_3", + "org.apache.pekko:pekko-protobuf-v3_3:jar:sources", + "org.apache.pekko:pekko-serialization-jackson_3", + "org.apache.pekko:pekko-serialization-jackson_3:jar:sources", + "org.apache.pekko:pekko-slf4j_3", + "org.apache.pekko:pekko-slf4j_3:jar:sources", + "org.apache.pekko:pekko-stream_3", + "org.apache.pekko:pekko-stream_3:jar:sources", "org.atteo.classindex:classindex", "org.atteo.classindex:classindex:jar:sources", "org.brotli:dec", @@ -3125,10 +3082,8 @@ "org.eclipse.jetty:jetty-io:jar:sources", "org.eclipse.jetty:jetty-util", "org.eclipse.jetty:jetty-util:jar:sources", - "org.hamcrest:hamcrest", "org.hamcrest:hamcrest-core", "org.hamcrest:hamcrest-core:jar:sources", - "org.hamcrest:hamcrest:jar:sources", "org.lz4:lz4-java", "org.lz4:lz4-java:jar:sources", "org.mockito:mockito-core", @@ -3137,42 +3092,42 @@ "org.objenesis:objenesis:jar:sources", "org.ow2.asm:asm", "org.ow2.asm:asm:jar:sources", - "org.playframework.twirl:twirl-api_2.13", - "org.playframework.twirl:twirl-api_2.13:jar:sources", + "org.playframework.twirl:twirl-api_3", + "org.playframework.twirl:twirl-api_3:jar:sources", "org.playframework:play-build-link", "org.playframework:play-build-link:jar:sources", - "org.playframework:play-configuration_2.13", - "org.playframework:play-configuration_2.13:jar:sources", + "org.playframework:play-configuration_3", + "org.playframework:play-configuration_3:jar:sources", "org.playframework:play-exceptions", "org.playframework:play-exceptions:jar:sources", - "org.playframework:play-functional_2.13", - "org.playframework:play-functional_2.13:jar:sources", - "org.playframework:play-guice_2.13", - "org.playframework:play-guice_2.13:jar:sources", - "org.playframework:play-json_2.13", - "org.playframework:play-json_2.13:jar:sources", - "org.playframework:play-server_2.13", - "org.playframework:play-server_2.13:jar:sources", - "org.playframework:play-specs2_2.13", - "org.playframework:play-specs2_2.13:jar:sources", - "org.playframework:play-streams_2.13", - "org.playframework:play-streams_2.13:jar:sources", - "org.playframework:play-test_2.13", - "org.playframework:play-test_2.13:jar:sources", - "org.playframework:play_2.13", - "org.playframework:play_2.13:jar:sources", + "org.playframework:play-functional_3", + "org.playframework:play-functional_3:jar:sources", + "org.playframework:play-guice_3", + "org.playframework:play-guice_3:jar:sources", + "org.playframework:play-json_3", + "org.playframework:play-json_3:jar:sources", + "org.playframework:play-server_3", + "org.playframework:play-server_3:jar:sources", + "org.playframework:play-specs2_3", + "org.playframework:play-specs2_3:jar:sources", + "org.playframework:play-streams_3", + "org.playframework:play-streams_3:jar:sources", + "org.playframework:play-test_3", + "org.playframework:play-test_3:jar:sources", + "org.playframework:play_3", + "org.playframework:play_3:jar:sources", "org.portable-scala:portable-scala-reflect_2.13", "org.portable-scala:portable-scala-reflect_2.13:jar:sources", "org.reactivestreams:reactive-streams", "org.reactivestreams:reactive-streams:jar:sources", - "org.scala-lang.modules:scala-parser-combinators_2.13", - "org.scala-lang.modules:scala-parser-combinators_2.13:jar:sources", - "org.scala-lang.modules:scala-xml_2.13", - "org.scala-lang.modules:scala-xml_2.13:jar:sources", + "org.scala-lang.modules:scala-parser-combinators_3", + "org.scala-lang.modules:scala-parser-combinators_3:jar:sources", + "org.scala-lang.modules:scala-xml_3", + "org.scala-lang.modules:scala-xml_3:jar:sources", "org.scala-lang:scala-library", "org.scala-lang:scala-library:jar:sources", - "org.scala-lang:scala-reflect", - "org.scala-lang:scala-reflect:jar:sources", + "org.scala-lang:scala3-library_3", + "org.scala-lang:scala3-library_3:jar:sources", "org.scala-sbt:test-interface", "org.scala-sbt:test-interface:jar:sources", "org.seleniumhq.selenium:htmlunit-driver", @@ -3201,18 +3156,16 @@ "org.slf4j:jul-to-slf4j:jar:sources", "org.slf4j:slf4j-api", "org.slf4j:slf4j-api:jar:sources", - "org.specs2:specs2-common_2.13", - "org.specs2:specs2-common_2.13:jar:sources", - "org.specs2:specs2-core_2.13", - "org.specs2:specs2-core_2.13:jar:sources", - "org.specs2:specs2-fp_2.13", - "org.specs2:specs2-fp_2.13:jar:sources", - "org.specs2:specs2-junit_2.13", - "org.specs2:specs2-junit_2.13:jar:sources", - "org.specs2:specs2-matcher_2.13", - "org.specs2:specs2-matcher_2.13:jar:sources", - "org.specs2:specs2-mock_2.13", - "org.specs2:specs2-mock_2.13:jar:sources" + "org.specs2:specs2-common_3", + "org.specs2:specs2-common_3:jar:sources", + "org.specs2:specs2-core_3", + "org.specs2:specs2-core_3:jar:sources", + "org.specs2:specs2-fp_3", + "org.specs2:specs2-fp_3:jar:sources", + "org.specs2:specs2-junit_3", + "org.specs2:specs2-junit_3:jar:sources", + "org.specs2:specs2-matcher_3", + "org.specs2:specs2-matcher_3:jar:sources" ] }, "services": { @@ -3292,12 +3245,12 @@ "com.fasterxml.jackson.module.paramnames.ParameterNamesModule" ] }, - "com.fasterxml.jackson.module:jackson-module-scala_2.13": { + "com.fasterxml.jackson.module:jackson-module-scala_3": { "com.fasterxml.jackson.databind.Module": [ "com.fasterxml.jackson.module.scala.DefaultScalaModule" ] }, - "com.fasterxml.jackson.module:jackson-module-scala_2.13:jar:sources": { + "com.fasterxml.jackson.module:jackson-module-scala_3:jar:sources": { "com.fasterxml.jackson.databind.Module": [ "com.fasterxml.jackson.module.scala.DefaultScalaModule" ] diff --git a/test/BUILD.bazel b/test/BUILD.bazel index a9e9130..e702acc 100644 --- a/test/BUILD.bazel +++ b/test/BUILD.bazel @@ -84,15 +84,15 @@ scala_test( ], deps = [ "@play_routes_compiler_cli_test_maven//:javax_inject_javax_inject", - "@play_routes_compiler_cli_test_maven//:org_apache_pekko_pekko_actor_2_13", - "@play_routes_compiler_cli_test_maven//:org_playframework_play_2_13", - "@play_routes_compiler_cli_test_maven//:org_playframework_play_configuration_2_13", - "@play_routes_compiler_cli_test_maven//:org_playframework_play_guice_2_13", - "@play_routes_compiler_cli_test_maven//:org_playframework_play_specs2_2_13", - "@play_routes_compiler_cli_test_maven//:org_playframework_play_test_2_13", - "@play_routes_compiler_cli_test_maven//:org_specs2_specs2_common_2_13", - "@play_routes_compiler_cli_test_maven//:org_specs2_specs2_core_2_13", - "@play_routes_compiler_cli_test_maven//:org_specs2_specs2_matcher_2_13", + "@play_routes_compiler_cli_test_maven//:org_apache_pekko_pekko_actor_3", + "@play_routes_compiler_cli_test_maven//:org_playframework_play_3", + "@play_routes_compiler_cli_test_maven//:org_playframework_play_configuration_3", + "@play_routes_compiler_cli_test_maven//:org_playframework_play_guice_3", + "@play_routes_compiler_cli_test_maven//:org_playframework_play_specs2_3", + "@play_routes_compiler_cli_test_maven//:org_playframework_play_test_3", + "@play_routes_compiler_cli_test_maven//:org_specs2_specs2_common_3", + "@play_routes_compiler_cli_test_maven//:org_specs2_specs2_core_3", + "@play_routes_compiler_cli_test_maven//:org_specs2_specs2_matcher_3", ], ) @@ -122,15 +122,15 @@ scala_test( deps = [ ":common", "@play_routes_compiler_cli_test_maven//:javax_inject_javax_inject", - "@play_routes_compiler_cli_test_maven//:org_apache_pekko_pekko_actor_2_13", - "@play_routes_compiler_cli_test_maven//:org_playframework_play_2_13", - "@play_routes_compiler_cli_test_maven//:org_playframework_play_configuration_2_13", - "@play_routes_compiler_cli_test_maven//:org_playframework_play_guice_2_13", - "@play_routes_compiler_cli_test_maven//:org_playframework_play_specs2_2_13", - "@play_routes_compiler_cli_test_maven//:org_playframework_play_test_2_13", - "@play_routes_compiler_cli_test_maven//:org_specs2_specs2_common_2_13", - "@play_routes_compiler_cli_test_maven//:org_specs2_specs2_core_2_13", - "@play_routes_compiler_cli_test_maven//:org_specs2_specs2_matcher_2_13", + "@play_routes_compiler_cli_test_maven//:org_apache_pekko_pekko_actor_3", + "@play_routes_compiler_cli_test_maven//:org_playframework_play_3", + "@play_routes_compiler_cli_test_maven//:org_playframework_play_configuration_3", + "@play_routes_compiler_cli_test_maven//:org_playframework_play_guice_3", + "@play_routes_compiler_cli_test_maven//:org_playframework_play_specs2_3", + "@play_routes_compiler_cli_test_maven//:org_playframework_play_test_3", + "@play_routes_compiler_cli_test_maven//:org_specs2_specs2_common_3", + "@play_routes_compiler_cli_test_maven//:org_specs2_specs2_core_3", + "@play_routes_compiler_cli_test_maven//:org_specs2_specs2_matcher_3", ], ) @@ -141,6 +141,6 @@ scala_library( ":play-routes-reverse-router-only", ], deps = [ - "@play_routes_compiler_cli_test_maven//:org_playframework_play_2_13", + "@play_routes_compiler_cli_test_maven//:org_playframework_play_3", ], ) diff --git a/test/PlayForwardRoutesOnlyTest.scala b/test/PlayForwardRoutesOnlyTest.scala index 6a28a46..d3b63e7 100644 --- a/test/PlayForwardRoutesOnlyTest.scala +++ b/test/PlayForwardRoutesOnlyTest.scala @@ -13,7 +13,9 @@ class PlayForwardRoutesOnlyTest extends Specification { "Play Routes Compiler when run through Bazel" should { "Compiles forward routes correctly" in new WithApplication(app) { withApp => - status(route(withApp.app, FakeRequest(GET, TestReverseRoutesOnly.generate(10))).get) mustEqual OK + override def running() = { + status(route(withApp.app, FakeRequest(GET, TestReverseRoutesOnly.generate(10))).get) mustEqual OK + } } } } \ No newline at end of file diff --git a/test/PlayReverseRoutesOnlyTest.scala b/test/PlayReverseRoutesOnlyTest.scala index d6a93f4..52b1836 100644 --- a/test/PlayReverseRoutesOnlyTest.scala +++ b/test/PlayReverseRoutesOnlyTest.scala @@ -12,11 +12,13 @@ class PlayReverseRoutesOnlyTest extends Specification { "Play Routes Compiler when run through Bazel" should { "Compiles reverse routes in shared project correctly" in new WithApplication(app) { withApp => - // The common project generates the correct reverse route. - TestReverseRoutesOnly.generate(10) mustEqual("/okReverseAgain/10") + override def running() = { + // The common project generates the correct reverse route. + TestReverseRoutesOnly.generate(10) mustEqual("/okReverseAgain/10") - // This verifies availability of the reverse route for the test target. - ReverseRoutesController.anotherOk(20).path mustEqual("/okReverseAgain/20") + // This verifies availability of the reverse route for the test target. + ReverseRoutesController.anotherOk(20).path mustEqual("/okReverseAgain/20") + } } } diff --git a/test/PlayRoutesCompilerTest.scala b/test/PlayRoutesCompilerTest.scala index 287426d..84bab64 100644 --- a/test/PlayRoutesCompilerTest.scala +++ b/test/PlayRoutesCompilerTest.scala @@ -15,36 +15,49 @@ class PlayRoutesCompilerTest extends Specification { "Play Routes Compiler when run through Bazel" should { "Compile Play routes" in new WithApplication(application) { withApp => - status(route(withApp.app, FakeRequest(GET, "/ok")).get) mustEqual OK - status(route(withApp.app, FakeRequest(GET, "/badRequest")).get) mustEqual BAD_REQUEST - status(route(withApp.app, FakeRequest(GET, "/500")).get) mustEqual INTERNAL_SERVER_ERROR + override def running() = { + status(route(withApp.app, FakeRequest(GET, "/ok")).get) mustEqual OK + status(route(withApp.app, FakeRequest(GET, "/badRequest")).get) mustEqual BAD_REQUEST + status(route(withApp.app, FakeRequest(GET, "/500")).get) mustEqual INTERNAL_SERVER_ERROR + } } "Handle Large Routes files well" in new WithApplication(application) { withApp => - status(route(withApp.app, FakeRequest(GET, "/large/749")).get) mustEqual OK + override def running() = { + status(route(withApp.app, FakeRequest(GET, "/large/749")).get) mustEqual OK + } } "Support multiple routes files" in new WithApplication(application) { withApp => - status(route(withApp.app, FakeRequest(GET, "/ok2")).get) mustEqual OK - status(route(withApp.app, FakeRequest(GET, "/ok3")).get) mustEqual OK + override def running() = { + status(route(withApp.app, FakeRequest(GET, "/ok2")).get) mustEqual OK + status(route(withApp.app, FakeRequest(GET, "/ok3")).get) mustEqual OK + } } "Add additional imports when specified" in new WithApplication(application) { withApp => - status(route(withApp.app, FakeRequest(GET, "/okUser/1")).get) mustEqual OK + override def running() = { + status(route(withApp.app, FakeRequest(GET, "/okUser/1")).get) mustEqual OK + } } "Use the specified routes generator" in new WithApplication(application) { withApp => - status(route(withApp.app, FakeRequest(GET, "/okGenerator")).get) mustEqual OK + override def running() = { + status(route(withApp.app, FakeRequest(GET, "/okGenerator")).get) mustEqual OK + } } "Generate reverse routes when specified" in new WithApplication(application) { withApp => - val myRoute = ReverseRoutesController.ok(3).toString - val result = route(withApp.app, FakeRequest(GET, myRoute)).get - status(result) mustEqual OK + override def running() = { + val myRoute = ReverseRoutesController.ok(3).toString + val result = route(withApp.app, FakeRequest(GET, myRoute)).get + status(result) mustEqual OK + } } // TODO: Add this test once I figure out what this does - // "Namespace the reverse router when specified" in new WithApplication() { + // "Namespace the reverse router when specified" in new WithApplication(application) { with App => + // override def running() = {} // } } } \ No newline at end of file diff --git a/test_workspace.bzl b/test_workspace.bzl index 54e3ccf..2112cc1 100644 --- a/test_workspace.bzl +++ b/test_workspace.bzl @@ -11,12 +11,12 @@ def play_routes_compiler_cli_test_repositories(): maven_install( name = "play_routes_compiler_cli_test_maven", artifacts = [ - "org.specs2:specs2-common_2.13:{}".format(specs2_version), - "org.specs2:specs2-core_2.13:{}".format(specs2_version), - "org.specs2:specs2-matcher_2.13:{}".format(specs2_version), - "org.playframework:play_2.13:{}".format(play_version), - "org.playframework:play-test_2.13:{}".format(play_version), - "org.playframework:play-specs2_2.13:{}".format(play_version), + "org.specs2:specs2-common_3:{}".format(specs2_version), + "org.specs2:specs2-core_3:{}".format(specs2_version), + "org.specs2:specs2-matcher_3:{}".format(specs2_version), + "org.playframework:play_3:{}".format(play_version), + "org.playframework:play-test_3:{}".format(play_version), + "org.playframework:play-specs2_3:{}".format(play_version), ], repositories = [ "https://repo.maven.apache.org/maven2", From 8abfbe51ebc183934427385e74b63e6d2a6e73f9 Mon Sep 17 00:00:00 2001 From: James Judd Date: Wed, 4 Sep 2024 16:57:50 -0600 Subject: [PATCH 3/3] Use multiplex sandboxing on the default Java toolchain rules_scala_annex supports it and we now support it, so we might as well use it. --- BUILD | 1 + WORKSPACE | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/BUILD b/BUILD index 63a0216..2730474 100644 --- a/BUILD +++ b/BUILD @@ -10,6 +10,7 @@ default_java_toolchain( name = "repository_default_toolchain_21", configuration = DEFAULT_TOOLCHAIN_CONFIGURATION, java_runtime = "@rules_java//toolchains:remotejdk_21", + javac_supports_worker_multiplex_sandboxing = True, # some of the default options make scala compilation fail in the test package misc = [opt for opt in DEFAULT_JAVACOPTS if not opt.startswith("-Xep")], source_version = "21", diff --git a/WORKSPACE b/WORKSPACE index eedeed7..8990c57 100644 --- a/WORKSPACE +++ b/WORKSPACE @@ -5,9 +5,9 @@ load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") # rules_java http_archive( name = "rules_java", - sha256 = "647bb31c0d51882549def6f67ee9078df697043406ed4a5144bbdf3b17f91e33", + sha256 = "41131de4417de70b9597e6ebd515168ed0ba843a325dc54a81b92d7af9a7b3ea", urls = [ - "https://github.com/bazelbuild/rules_java/releases/download/7.8.0/rules_java-7.8.0.tar.gz", + "https://github.com/bazelbuild/rules_java/releases/download/7.9.0/rules_java-7.9.0.tar.gz", ], )