187 lines
8.3 KiB
Java
187 lines
8.3 KiB
Java
package io.gitlab.jfronny.inceptum.common;
|
|
|
|
import io.gitlab.jfronny.commons.OSUtils;
|
|
import io.gitlab.jfronny.inceptum.common.api.MavenApi;
|
|
import io.gitlab.jfronny.inceptum.common.model.inceptum.*;
|
|
import io.gitlab.jfronny.inceptum.common.model.maven.*;
|
|
import org.jetbrains.annotations.Nullable;
|
|
import org.xml.sax.SAXException;
|
|
|
|
import javax.xml.stream.XMLStreamException;
|
|
import java.io.File;
|
|
import java.io.IOException;
|
|
import java.net.URISyntaxException;
|
|
import java.nio.file.Files;
|
|
import java.nio.file.Path;
|
|
import java.util.*;
|
|
import java.util.function.Consumer;
|
|
import java.util.stream.Collectors;
|
|
import java.util.stream.Stream;
|
|
|
|
public class Updater {
|
|
private static final String ARTIFACTS_URL = "https://pages.frohnmeyer-wds.de/JfMods/Inceptum/artifacts/";
|
|
private static final String STABLE_URL = "https://pages.frohnmeyer-wds.de/JfMods/Inceptum/stable/";
|
|
public static final String PROJECT_MAVEN = "https://maven.frohnmeyer-wds.de/artifacts/";
|
|
|
|
public static UpdateMetadata getUpdate() {
|
|
return Updater.check(InceptumConfig.channel, true, channel -> {
|
|
Utils.LOGGER.error("No stable version was found, switching to experimental channel");
|
|
InceptumConfig.channel = channel;
|
|
InceptumConfig.saveConfig();
|
|
});
|
|
}
|
|
|
|
public static void update(UpdateMetadata source, boolean relaunch) throws IOException, URISyntaxException {
|
|
if (Runtime.version().feature() < source.jvm) {
|
|
throw new OutdatedException("A newer JVM version is required for the current build of Inceptum. Please update!");
|
|
} else if (source.wrapperVersion > BuildMetadata.WRAPPER_VERSION) {
|
|
throw new OutdatedException("The current build of Inceptum requires a newer wrapper version. Please update!");
|
|
} else if (source.wrapperVersion < BuildMetadata.WRAPPER_VERSION) {
|
|
throw new OutdatedException("The current build of Inceptum requires an older wrapper version. Please update!");
|
|
}
|
|
|
|
Utils.LOGGER.info("Downloading version " + source.version);
|
|
|
|
WrapperConfig config = new WrapperConfig();
|
|
config.natives = new HashMap<>();
|
|
config.libraries = new LinkedHashSet<>();
|
|
config.repositories = new LinkedHashSet<>(source.repositories);
|
|
source.natives.forEach((k, v) -> config.natives.put(k, new LinkedHashSet<>(v)));
|
|
|
|
DependencyNode node = downloadLibrary(source.repositories, "io.gitlab.jfronny.inceptum:launcher-dist:" + source.version, config.libraries);
|
|
Utils.LOGGER.info("Downloaded Dependencies:\n" + node);
|
|
|
|
List<String> currentLibraries = new LinkedList<>(config.libraries);
|
|
if (source.natives.containsKey(Utils.getCurrentFlavor())) {
|
|
Set<String> natives = new LinkedHashSet<>();
|
|
for (String lib : source.natives.get(Utils.getCurrentFlavor())){
|
|
downloadLibrary(source.repositories, lib, natives);
|
|
}
|
|
currentLibraries.addAll(natives);
|
|
config.natives.put(Utils.getCurrentFlavor(), natives);
|
|
}
|
|
|
|
GC_WrapperConfig.write(MetaHolder.WRAPPER_CONFIG_PATH, config);
|
|
|
|
if (relaunch) {
|
|
Runtime.getRuntime().addShutdownHook(new Thread(() -> {
|
|
try {
|
|
new ProcessBuilder(OSUtils.getJvmBinary(),
|
|
"-cp",
|
|
buildClasspath(currentLibraries.stream())
|
|
.map(Path::toString)
|
|
.collect(Collectors.joining("" + File.pathSeparatorChar))
|
|
).inheritIO().start();
|
|
} catch (IOException e) {
|
|
Utils.LOGGER.error("Could not relaunch", e);
|
|
}
|
|
}));
|
|
}
|
|
}
|
|
|
|
public static List<Path> getLaunchClasspath(WrapperConfig wrapperConfig) throws IOException, URISyntaxException {
|
|
Set<String> natives = wrapperConfig.natives.get(Utils.getCurrentFlavor());
|
|
if (natives == null) natives = new LinkedHashSet<>();
|
|
Set<String> libs = wrapperConfig.libraries;
|
|
if (libs == null) libs = new LinkedHashSet<>();
|
|
|
|
boolean configChanged = false;
|
|
|
|
for (String lib : libs) {
|
|
Path p = artifactToPath(lib);
|
|
if (!Files.exists(p)) {
|
|
configChanged = true;
|
|
downloadLibrary(wrapperConfig.repositories, lib, libs);
|
|
}
|
|
}
|
|
for (String lib : natives) {
|
|
Path p = artifactToPath(lib);
|
|
if (!Files.exists(p)) {
|
|
configChanged = true;
|
|
downloadLibrary(wrapperConfig.repositories, lib, natives);
|
|
}
|
|
}
|
|
|
|
if (configChanged) GC_WrapperConfig.write(MetaHolder.WRAPPER_CONFIG_PATH, wrapperConfig);
|
|
|
|
return buildClasspath(Stream.concat(libs.stream(), natives.stream())).toList();
|
|
}
|
|
|
|
private static Stream<Path> buildClasspath(Stream<String> libraries) {
|
|
return libraries.map(Updater::artifactToPath);
|
|
}
|
|
|
|
private static DependencyNode downloadLibrary(Set<String> repositories, final String artifact, Set<String> libraries) throws IOException, URISyntaxException {
|
|
List<Exception> exceptions = new LinkedList<>();
|
|
for (String repository : Stream.concat(Stream.of(PROJECT_MAVEN), repositories.stream()).toList()) {
|
|
Pom pom;
|
|
try {
|
|
pom = MavenApi.getPom(repository, artifact);
|
|
} catch (IOException | URISyntaxException | XMLStreamException | SAXException e) {
|
|
exceptions.add(new Exception("Could not download artifact from " + repository, e));
|
|
continue;
|
|
}
|
|
Set<DependencyNode> dependencies = new LinkedHashSet<>();
|
|
if (pom.dependencies != null) {
|
|
for (MavenDependency dependency : pom.dependencies) {
|
|
String mvnName = dependency.groupId + ":" + dependency.artifactId + ":" + dependency.version;
|
|
dependencies.add(downloadLibrary(repositories, mvnName, libraries));
|
|
}
|
|
}
|
|
MavenApi.downloadLibrary(repository, pom);
|
|
libraries.add(artifact);
|
|
return new DependencyNode(pom, dependencies);
|
|
}
|
|
IOException exception = new IOException("Could not find any repository containing the artifact " + artifact + " (searched: " + String.join(", ", repositories) + ")");
|
|
for (Exception e : exceptions) {
|
|
exception.addSuppressed(e);
|
|
}
|
|
throw exception;
|
|
}
|
|
|
|
private static Path artifactToPath(String artifact) {
|
|
return MetaHolder.LIBRARIES_DIR.resolve(MavenApi.mavenNotationToJarPath(artifact)).toAbsolutePath();
|
|
}
|
|
|
|
public static @Nullable UpdateMetadata check(UpdateChannel channel, boolean versionCompare, Consumer<UpdateChannel> channelInvalid) {
|
|
try {
|
|
UpdateMetadata experimental = Net.downloadObject(ARTIFACTS_URL + "version.json", GC_UpdateMetadata::read);
|
|
UpdateMetadata stable = null;
|
|
try {
|
|
stable = Net.downloadObject(STABLE_URL + "version.json", GC_UpdateMetadata::read);
|
|
} catch (Throwable ignored) {}
|
|
if (stable == null && channel == UpdateChannel.Stable) {
|
|
channel = UpdateChannel.CI;
|
|
channelInvalid.accept(channel);
|
|
}
|
|
UpdateMetadata info = switch (channel) {
|
|
case CI -> experimental;
|
|
case Stable -> stable;
|
|
};
|
|
if (info.jvm > Runtime.version().feature()) {
|
|
//TODO visual indication for this
|
|
Utils.LOGGER.error("A newer JVM is required to use the latest inceptum version. Please update!");
|
|
return null;
|
|
}
|
|
if (versionCompare) {
|
|
Utils.LOGGER.info("Latest version is " + info.version + ", current is " + BuildMetadata.VERSION);
|
|
if (BuildMetadata.BUILD_TIME >= info.buildTime) {
|
|
Utils.LOGGER.info("Up-to-date");
|
|
return null;
|
|
}
|
|
}
|
|
return info;
|
|
} catch (IOException e) {
|
|
Utils.LOGGER.error("Could not check for updates", e);
|
|
}
|
|
return null;
|
|
}
|
|
|
|
public static String getShadowJarUrl(UpdateChannel channel) {
|
|
return switch (channel) {
|
|
case CI -> ARTIFACTS_URL;
|
|
case Stable -> STABLE_URL;
|
|
} + "/Inceptum-" + Utils.getCurrentFlavor() + ".jar";
|
|
}
|
|
}
|