diff --git a/build.gradle b/build.gradle index f331bfe..f54c98c 100644 --- a/build.gradle +++ b/build.gradle @@ -41,7 +41,7 @@ configurations { } dependencies { - compileOnly 'org.jetbrains:annotations:24.0.0' + compileOnly 'org.jetbrains:annotations:24.1.0' // When updating shade dependencies, you must also run the generateDependencyHashes task shade 'org.slf4j:slf4j-api:2.0.12' @@ -104,8 +104,8 @@ tasks.named('idea').configure { } tasks.named('jar', Jar).configure { - from('gradle') { - into 'gradle' + from('gradle/wrapper') { + into 'gradle/wrapper' } manifest { attributes([ @@ -119,8 +119,8 @@ tasks.named('shadowJar', ShadowJar).configure { archiveClassifier = 'all' configurations = [project.configurations.shade] - from('gradle') { - into 'gradle' + from('gradle/wrapper') { + into 'gradle/wrapper' rename '(.+).jar', '$1.zip' } diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 3fa8f86..b82aa23 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.4-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-bin.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME diff --git a/gradlew b/gradlew index 0adc8e1..1aa94a4 100644 --- a/gradlew +++ b/gradlew @@ -145,7 +145,7 @@ if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then case $MAX_FD in #( max*) # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. - # shellcheck disable=SC3045 + # shellcheck disable=SC2039,SC3045 MAX_FD=$( ulimit -H -n ) || warn "Could not query maximum file descriptor limit" esac @@ -153,7 +153,7 @@ if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then '' | soft) :;; #( *) # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. - # shellcheck disable=SC3045 + # shellcheck disable=SC2039,SC3045 ulimit -n "$MAX_FD" || warn "Could not set maximum file descriptor limit to $MAX_FD" esac @@ -202,11 +202,11 @@ fi # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' -# Collect all arguments for the java command; -# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of -# shell script including quotes and variable substitutions, so put them in -# double quotes to make sure that they get re-expanded; and -# * put everything else in single quotes, so that it's not re-expanded. +# Collect all arguments for the java command: +# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, +# and any embedded shellness will be escaped. +# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be +# treated as '${Hostname}' itself on the command line. set -- \ "-Dorg.gradle.appname=$APP_BASE_NAME" \ diff --git a/settings.gradle b/settings.gradle index 7ec2c9b..4eb2e9f 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1,5 +1,5 @@ plugins { - id 'org.gradle.toolchains.foojay-resolver-convention' version '0.7.0' + id 'org.gradle.toolchains.foojay-resolver-convention' version '0.8.0' } rootProject.name = 'Snowblower' diff --git a/src/main/java/net/neoforged/snowblower/Generator.java b/src/main/java/net/neoforged/snowblower/Generator.java index 2e3418e..f429966 100644 --- a/src/main/java/net/neoforged/snowblower/Generator.java +++ b/src/main/java/net/neoforged/snowblower/Generator.java @@ -119,7 +119,7 @@ public Generator setup(String branchName, @Nullable URL remoteUrl, boolean check var cfgBranch = cfg.branches() == null ? null : cfg.branches().get(branchName); if (cfgBranch == null) { - if (cliBranch.start() == null && cliBranch.end() == null && cliBranch.versions() == null) + if (cliBranch.start() == null && cliBranch.end() == null) throw new IllegalArgumentException("Unknown branch config: " + branchName); this.branch = cliBranch; } else { @@ -127,7 +127,9 @@ public Generator setup(String branchName, @Nullable URL remoteUrl, boolean check cfgBranch.type(), cliBranch.start() == null ? cfgBranch.start() : cliBranch.start(), cliBranch.end() == null ? cfgBranch.end() : cliBranch.end(), - cfgBranch.versions() + cfgBranch.versions(), + cfgBranch.includeVersions(), + cfgBranch.excludeVersions() ); } @@ -241,21 +243,23 @@ private void runInternal() throws IOException, GitAPIException { if (manifest.versions() == null) throw new IllegalStateException("Failed to find versions, manifest missing versions listing"); - var versions = Arrays.asList(manifest.versions()); - /* Sort the list by release time.. in case Mojang screwed it up? - Arrays.stream(manifest.versions()) - .sorted((a,b) -> b.releaseTime().compareTo(a.releaseTime())) // b to a, so its in descending order - .toList(); - */ + // Sorted from newest at index 0 to oldest at the end of the list + var versions = new ArrayList<>(Arrays.asList(manifest.versions())); var targetVer = this.branch.end(); // If we have explicit filters, apply them if (this.branch.versions() != null) { - versions = versions.stream().filter(v -> this.branch.versions().contains(v.id())).toList(); + versions.removeIf(v -> !this.branch.versions().contains(v.id())); if (targetVer == null) targetVer = versions.get(0).id(); } else { - versions = versions.stream().filter(v -> !v.id().getType().isSpecial()).toList(); + var exclude = versions.stream().filter(v -> v.id().getType().isSpecial()).map(VersionInfo::id).collect(Collectors.toList()); + if (this.branch.includeVersions() != null) + exclude.removeAll(this.branch.includeVersions()); + if (this.branch.excludeVersions() != null) + exclude.addAll(this.branch.excludeVersions()); + + versions.removeIf(v -> exclude.contains(v.id())); } // Find the latest version from the manifest @@ -267,8 +271,8 @@ private void runInternal() throws IOException, GitAPIException { if (this.branch.type().equals("release")) targetVer = lat.release(); else { - var release = versions.stream().filter(e -> !lat.release().equals(e.id())).findFirst().orElse(null); - var snapshot = versions.stream().filter(e -> !lat.snapshot().equals(e.id())).findFirst().orElse(null); + var release = versions.stream().filter(e -> lat.release().equals(e.id())).findFirst().orElse(null); + var snapshot = versions.stream().filter(e -> lat.snapshot().equals(e.id())).findFirst().orElse(null); if (release == null && snapshot == null) throw new IllegalStateException("Failed to find latest, manifest specified " + lat.release() + " and " + lat.snapshot() + " and both are missing"); if (release == null) @@ -314,8 +318,10 @@ else if (snapshot == null) } } - if (startIdx == -1 || endIdx == -1) - throw new IllegalStateException("Could not find start and/or end version in version manifest (or they were out of order)"); + if (startIdx == -1) + throw new IllegalStateException("Could not find start version in version list. Was it excluded? Start: " + startVer + ", End: " + targetVer); + if (endIdx == -1) + throw new IllegalStateException("Could not find end version in version list (or end version is earlier than start version). Was it excluded? Start: " + startVer + ", End: " + targetVer); List toGenerate = new ArrayList<>(versions.subList(endIdx, startIdx + 1)); if (this.branch.type().equals("release")) diff --git a/src/main/java/net/neoforged/snowblower/Main.java b/src/main/java/net/neoforged/snowblower/Main.java index b888260..9055239 100644 --- a/src/main/java/net/neoforged/snowblower/Main.java +++ b/src/main/java/net/neoforged/snowblower/Main.java @@ -92,7 +92,7 @@ public static void main(String[] args) throws Exception { var targetVer = options.has(targetVerO) ? MinecraftVersion.from(options.valueOf(targetVerO)) : null; if (targetVer != null && targetVer.compareTo(startVer) < 0) throw new IllegalArgumentException("Target version must be greater than or equal to start version"); - var cliBranch = new BranchSpec(options.has(releasesOnlyO) ? "release" : "all", startVer, targetVer, null); + var cliBranch = new BranchSpec(options.has(releasesOnlyO) ? "release" : "all", startVer, targetVer); String branchName = options.valueOf(branchNameO); @@ -101,14 +101,18 @@ public static void main(String[] args) throws Exception { URI configUri = options.valueOf(configO); try { URL url = configUri.toURL(); - cfg = Util.downloadJson(url, Config.class); + if ("file".equals(configUri.getScheme())) { + cfg = Config.load(Util.getPath(configUri)); + } else { + cfg = Util.downloadJson(url, Config.class); + } } catch (MalformedURLException e) { - cfg = Config.load(Util.getPath(configUri)); + throw new RuntimeException(e); } } else { Map branches = new HashMap<>(); - branches.put("release", new BranchSpec("release", null, null, null)); - branches.put("dev", new BranchSpec("all", null, null, null)); + branches.put("release", new BranchSpec("release", null, null)); + branches.put("dev", new BranchSpec("all", null, null)); cfg = new Config(branches); } diff --git a/src/main/java/net/neoforged/snowblower/data/Config.java b/src/main/java/net/neoforged/snowblower/data/Config.java index 6f61924..7921b7a 100644 --- a/src/main/java/net/neoforged/snowblower/data/Config.java +++ b/src/main/java/net/neoforged/snowblower/data/Config.java @@ -25,6 +25,12 @@ public record BranchSpec( String type, MinecraftVersion start, MinecraftVersion end, - List versions - ) {} + List versions, + List includeVersions, + List excludeVersions + ) { + public BranchSpec(String type, MinecraftVersion start, MinecraftVersion end) { + this(type, start, end, null, null, null); + } + } } diff --git a/src/main/java/net/neoforged/snowblower/tasks/enhance/EnhanceVersionTask.java b/src/main/java/net/neoforged/snowblower/tasks/enhance/EnhanceVersionTask.java index 274b4f4..5d14e29 100644 --- a/src/main/java/net/neoforged/snowblower/tasks/enhance/EnhanceVersionTask.java +++ b/src/main/java/net/neoforged/snowblower/tasks/enhance/EnhanceVersionTask.java @@ -4,18 +4,18 @@ */ package net.neoforged.snowblower.tasks.enhance; +import net.neoforged.snowblower.data.Version; +import net.neoforged.snowblower.util.HashFunction; + import java.io.IOException; import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; -import java.util.Collections; +import java.util.ArrayList; import java.util.List; import java.util.stream.Collectors; import java.util.stream.Stream; -import net.neoforged.snowblower.data.Version; -import net.neoforged.snowblower.util.HashFunction; - public class EnhanceVersionTask { // TODO: I moved this out to its own package even tho its only one function, because I'm curious if we can cache it. // And doing that via a package level would be useful. @@ -25,50 +25,63 @@ public class EnhanceVersionTask { * This also includes dependencies with bad OS filtering rules when they are needed on all systems for compiling. * Adding these to all generated Minecraft versions should be mostly safe. */ - private static final List EXTRA_DEPENDENCIES = List.of("org.jetbrains:annotations:24.0.0", "com.google.code.findbugs:jsr305:3.0.2", "ca.weblite:java-objc-bridge:1.1"); - private static final String GRADLE_CONTENT = """ - plugins { - id 'java' - } + private static final List EXTRA_DEPENDENCIES = List.of("org.jetbrains:annotations:24.1.0", "com.google.code.findbugs:jsr305:3.0.2", "ca.weblite:java-objc-bridge:1.1"); + private static final String BUILD_GRADLE_CONTENT = """ + plugins { + id 'java' + } - java { - toolchain { - languageVersion = JavaLanguageVersion.of(%java_version%) - } - } + java { + toolchain { + languageVersion = JavaLanguageVersion.of(%java_version%) + } + } - repositories { - mavenCentral() - maven { - name = 'Mojang' - url = 'https://libraries.minecraft.net/' - } - } + repositories { + mavenCentral() + maven { + name = 'Mojang' + url = 'https://libraries.minecraft.net/' + } + } - dependencies { - %deps% - } - """; + dependencies { + %deps% + } + """; + private static final String SETTINGS_GRADLE_CONTENT = """ + plugins { + id 'org.gradle.toolchains.foojay-resolver-convention' version '0.8.0' + } + """; public static List enhance(Path output, Version version) throws IOException { - var data = GRADLE_CONTENT - .replace("%java_version%", Integer.toString(version.javaVersion().majorVersion())) // This assumes the minimum to be 8 (which it is) - .replace("%deps%", Stream.concat(version.libraries().stream() - .filter(Version.Library::isAllowed) - .map(Version.Library::name), EXTRA_DEPENDENCIES.stream()) - .sorted() - .map(lib -> " implementation '" + lib + '\'') - .collect(Collectors.joining("\n"))) - .getBytes(StandardCharsets.UTF_8); + var buildData = BUILD_GRADLE_CONTENT + .replace("%java_version%", Integer.toString(version.javaVersion().majorVersion())) // This assumes the minimum to be 8 (which it is) + .replace("%deps%", Stream.concat(version.libraries().stream() + .filter(Version.Library::isAllowed) + .map(Version.Library::name), EXTRA_DEPENDENCIES.stream()) + .sorted() + .map(lib -> " implementation '" + lib + '\'') + .collect(Collectors.joining("\n"))) + .getBytes(StandardCharsets.UTF_8); + var settingsData = SETTINGS_GRADLE_CONTENT.getBytes(StandardCharsets.UTF_8); + + List added = new ArrayList<>(); + + writeCached(buildData, added, output.resolve("build.gradle")); + writeCached(settingsData, added, output.resolve("settings.gradle")); - var build = output.resolve("build.gradle"); - var existing = Files.exists(build) ? HashFunction.MD5.hash(build) : ""; + return added; + } + + private static void writeCached(byte[] data, List added, Path path) throws IOException { + var existing = Files.exists(path) ? HashFunction.MD5.hash(path) : ""; var created = HashFunction.MD5.hash(data); + if (!existing.equals(created)) { - Files.write(build, data); - return List.of(build); + Files.write(path, data); + added.add(path); } - return Collections.emptyList(); } - } diff --git a/src/main/java/net/neoforged/snowblower/tasks/init/InitTask.java b/src/main/java/net/neoforged/snowblower/tasks/init/InitTask.java index 4e24997..5051a87 100644 --- a/src/main/java/net/neoforged/snowblower/tasks/init/InitTask.java +++ b/src/main/java/net/neoforged/snowblower/tasks/init/InitTask.java @@ -108,7 +108,7 @@ public boolean validate(MinecraftVersion start) throws IOException, GitAPIExcept try { Path copyParentFolder = Util.isDev() ? Util.getSourcePath() : Util.getPath(Main.class.getResource("/resource_root.txt").toURI()).getParent(); - List toCopy = List.of("gradlew", "gradlew.bat", "gradle"); + List toCopy = List.of("gradlew", "gradlew.bat", "gradle/wrapper"); AddCommand addCmd = git.add(); for (String filename : toCopy) {