diff --git a/build.gradle.kts b/build.gradle.kts index 1bfd4a7073..3670202fc4 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,8 +1,8 @@ preRelease(true) -versionProjects(":common:api", version("6.0.0")) -versionProjects(":common:implementation", version("6.0.0")) -versionProjects(":platforms", version("6.0.0")) +versionProjects(":common:api", version("6.0.1")) +versionProjects(":common:implementation", version("6.0.1")) +versionProjects(":platforms", version("6.0.1")) allprojects { diff --git a/common/addons/structure-terrascript-loader/build.gradle.kts b/common/addons/structure-terrascript-loader/build.gradle.kts index 15b7f11075..62422cc790 100644 --- a/common/addons/structure-terrascript-loader/build.gradle.kts +++ b/common/addons/structure-terrascript-loader/build.gradle.kts @@ -1,6 +1,6 @@ import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar -version = version("1.0.0") +version = version("1.0.1") dependencies { api("commons-io:commons-io:2.7") diff --git a/common/api/src/main/java/com/dfsek/terra/api/util/generic/pair/Pair.java b/common/api/src/main/java/com/dfsek/terra/api/util/generic/pair/Pair.java index 58d1e73539..ad4c2c8798 100644 --- a/common/api/src/main/java/com/dfsek/terra/api/util/generic/pair/Pair.java +++ b/common/api/src/main/java/com/dfsek/terra/api/util/generic/pair/Pair.java @@ -11,6 +11,10 @@ import org.jetbrains.annotations.NotNull; import java.util.Objects; +import java.util.function.Consumer; +import java.util.function.Function; +import java.util.function.Predicate; +import java.util.function.UnaryOperator; public final class Pair { @@ -18,6 +22,38 @@ public final class Pair { private final L left; private final R right; + public static Function, Pair> mapLeft(Function function) { + return pair -> of(function.apply(pair.left), pair.right); + } + + public static Function, Pair> mapRight(Function function) { + return pair -> of(pair.left, function.apply(pair.right)); + } + + public static Predicate> testLeft(Predicate predicate) { + return pair -> predicate.test(pair.left); + } + + public static Predicate> testRight(Predicate predicate) { + return pair -> predicate.test(pair.right); + } + + public static Consumer> consumeLeft(Consumer consumer) { + return pair -> consumer.accept(pair.left); + } + + public static Consumer> consumeRight(Consumer consumer) { + return pair -> consumer.accept(pair.right); + } + + public static Function, R> unwrapRight() { + return pair -> pair.right; + } + + public static Function, L> unwrapLeft() { + return pair -> pair.left; + } + private Pair(L left, R right) { this.left = left; this.right = right; @@ -108,4 +144,9 @@ public boolean equals(Object obj) { return Objects.equals(this.left, that.left) && Objects.equals(this.right, that.right); } } + + @Override + public String toString() { + return String.format("{%s,%s}", left, right); + } } diff --git a/common/implementation/base/src/main/java/com/dfsek/terra/AbstractPlatform.java b/common/implementation/base/src/main/java/com/dfsek/terra/AbstractPlatform.java index 9509f38b9f..21ff745fe6 100644 --- a/common/implementation/base/src/main/java/com/dfsek/terra/AbstractPlatform.java +++ b/common/implementation/base/src/main/java/com/dfsek/terra/AbstractPlatform.java @@ -18,6 +18,9 @@ package com.dfsek.terra; import com.dfsek.tectonic.api.TypeRegistry; + +import com.dfsek.terra.api.util.generic.pair.Pair; + import org.apache.commons.io.FileUtils; import org.apache.commons.io.IOUtils; import org.jetbrains.annotations.NotNull; @@ -33,12 +36,15 @@ import java.io.UncheckedIOException; import java.net.URL; import java.nio.charset.StandardCharsets; +import java.nio.file.Files; import java.nio.file.Path; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.List; import java.util.Map; +import java.util.Set; +import java.util.stream.Collectors; import com.dfsek.terra.addon.BootstrapAddonLoader; import com.dfsek.terra.addon.DependencySorter; @@ -212,13 +218,71 @@ protected void dumpResources() { logger.info("No resources config found. Skipping resource dumping."); return; } + + Path data = getDataFolder().toPath(); + + Path addonsPath = data.resolve("addons"); + Set> paths = Files + .walk(addonsPath) + .map(path -> Pair.of(path, data.relativize(path).toString())) + + .map(Pair.mapRight(s -> { + if(s.contains("+")) { // remove commit hash + return s.substring(0, s.lastIndexOf('+')); + } + return s; + })) + + .filter(Pair.testRight(s -> s.contains("."))) // remove patch version + .map(Pair.mapRight(s -> s.substring(0, s.lastIndexOf('.')))) + + .filter(Pair.testRight(s -> s.contains("."))) // remove minor version + .map(Pair.mapRight(s -> s.substring(0, s.lastIndexOf('.')))) + + .collect(Collectors.toSet()); + + Set pathsNoMajor = paths + .stream() + .filter(Pair.testRight(s -> s.contains("."))) + .map(Pair.mapRight(s -> s.substring(0, s.lastIndexOf('.')))) // remove major version + .map(Pair.unwrapRight()) + .collect(Collectors.toSet()); + + + // Terra-aaa-aaa-1.2.3-BETA+1e6af8923d.jar String resourceYaml = IOUtils.toString(resourcesConfig, StandardCharsets.UTF_8); Map> resources = new Yaml().load(resourceYaml); resources.forEach((dir, entries) -> entries.forEach(entry -> { - String resourcePath = String.format("%s/%s", dir, entry); + String resourcePath = dir + File.separatorChar + entry; File resource = new File(getDataFolder(), resourcePath); if(resource.exists()) return; // dont overwrite + + paths + .stream() + .filter(Pair.testRight(resourcePath::startsWith)) + .forEach(Pair.consumeLeft(path -> { + logger.info("Removing outdated resource {}, replacing with {}", path, resourcePath); + try { + Files.delete(path); + } catch(IOException e) { + throw new UncheckedIOException(e); + } + })); + + if(pathsNoMajor + .stream() + .anyMatch(resourcePath::startsWith) && // if any share name + paths + .stream() + .map(Pair.unwrapRight()) + .noneMatch(resourcePath::startsWith)) { // but dont share major version + logger.warn( + "Addon {} has a new major version available. It will not be automatically updated; you will need to ensure " + + "compatibility and update manually.", + resourcePath); + } + logger.info("Dumping resource {}...", resource.getAbsolutePath()); try { resource.getParentFile().mkdirs();