Fix maven downloads with -SNAPSHOT
ci/woodpecker/push/docs Pipeline was successful Details
ci/woodpecker/push/woodpecker Pipeline was successful Details

This commit is contained in:
Johannes Frohnmeyer 2022-11-04 12:41:41 +01:00
parent 11a40975d9
commit 0b65231175
Signed by: Johannes
GPG Key ID: E76429612C2929F4
7 changed files with 170 additions and 119 deletions

View File

@ -8,8 +8,7 @@ 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.io.*;
import java.net.URISyntaxException;
import java.nio.file.Files;
import java.nio.file.Path;
@ -19,9 +18,9 @@ import java.util.stream.Collectors;
import java.util.stream.Stream;
public class Updater {
public static final String PROJECT_MAVEN = "https://maven.frohnmeyer-wds.de/artifacts/";
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 -> {
@ -88,14 +87,14 @@ public class Updater {
boolean configChanged = false;
for (String lib : libs) {
Path p = artifactToPath(lib);
Path p = ArtifactMeta.parse(lib).getLocalPath();
if (!Files.exists(p)) {
configChanged = true;
downloadLibrary(wrapperConfig.repositories, lib, libs);
}
}
for (String lib : natives) {
Path p = artifactToPath(lib);
Path p = ArtifactMeta.parse(lib).getLocalPath();
if (!Files.exists(p)) {
configChanged = true;
downloadLibrary(wrapperConfig.repositories, lib, natives);
@ -108,18 +107,28 @@ public class Updater {
}
private static Stream<Path> buildClasspath(Stream<String> libraries) {
return libraries.map(Updater::artifactToPath);
return libraries.map(ArtifactMeta::parse).map(ArtifactMeta::getLocalPath);
}
private static DependencyNode downloadLibrary(Set<String> repositories, final String artifact, Set<String> libraries) throws IOException, URISyntaxException {
List<Exception> exceptions = new LinkedList<>();
List<FileNotFoundException> suppressed = new LinkedList<>();
for (String repository : Stream.concat(Stream.of(PROJECT_MAVEN), repositories.stream()).toList()) {
ArtifactMeta meta;
try {
meta = MavenApi.getMetadata(repository, artifact);
} catch (FileNotFoundException ignored) {
meta = ArtifactMeta.parse(artifact);
} catch (IOException | URISyntaxException | SAXException e) {
throw new IOException("Could not download artifact from " + repository, e);
}
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));
pom = MavenApi.getPom(repository, meta);
} catch (FileNotFoundException notFound) {
suppressed.add(notFound);
continue;
} catch (IOException | URISyntaxException | XMLStreamException | SAXException e) {
throw new IOException("Could not download artifact " + meta.getMavenNotation() + " from " + repository, e);
}
Set<DependencyNode> dependencies = new LinkedHashSet<>();
if (pom.dependencies != null) {
@ -128,19 +137,13 @@ public class Updater {
dependencies.add(downloadLibrary(repositories, mvnName, libraries));
}
}
MavenApi.downloadLibrary(repository, pom);
MavenApi.downloadLibrary(repository, meta);
libraries.add(artifact);
return new DependencyNode(pom, dependencies);
return new DependencyNode(artifact, 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();
IOException e = new IOException("Could not find any repository containing the artifact " + artifact + " (searched: " + String.join(", ", repositories) + ")");
for (FileNotFoundException ex : suppressed) e.addSuppressed(ex);
throw e;
}
public static @Nullable UpdateMetadata check(UpdateChannel channel, boolean versionCompare, Consumer<UpdateChannel> channelInvalid) {

View File

@ -2,8 +2,7 @@ package io.gitlab.jfronny.inceptum.common.api;
import io.gitlab.jfronny.commons.HttpUtils;
import io.gitlab.jfronny.inceptum.common.*;
import io.gitlab.jfronny.inceptum.common.model.maven.MavenDependency;
import io.gitlab.jfronny.inceptum.common.model.maven.Pom;
import io.gitlab.jfronny.inceptum.common.model.maven.*;
import org.jetbrains.annotations.Nullable;
import org.w3c.dom.*;
import org.xml.sax.SAXException;
@ -28,25 +27,14 @@ public class MavenApi {
}
}
public static Path downloadLibrary(String repo, Pom pom) throws IOException, URISyntaxException {
String artifact = pom.groupId + ':' + pom.artifactId + ':' + pom.version;
String rawArtifact = artifact;
if (pom.classifier != null || pom.snapshotVersion != null) {
artifact += ':';
if (pom.snapshotVersion != null) artifact += pom.snapshotVersion;
if (pom.classifier != null) {
if (pom.snapshotVersion != null) artifact += '-';
artifact += pom.classifier;
}
}
if (pom.classifier != null) rawArtifact += ':' + pom.classifier;
Path res = MetaHolder.LIBRARIES_DIR.resolve(mavenNotationToJarPath(rawArtifact));
Net.downloadFile(Utils.join("/", repo, mavenNotationToJarPath(artifact)), res);
public static Path downloadLibrary(String repo, ArtifactMeta meta) throws IOException, URISyntaxException {
Path res = meta.getLocalPath();
Net.downloadFile(Utils.join("/", repo, meta.getJarPath(true)), res);
return res;
}
public static Pom getPom(String repo, String artifact) throws IOException, SAXException, URISyntaxException, XMLStreamException {
try (InputStream is = HttpUtils.get(Utils.join("/", repo, mavenNotationToPomPath(artifact))).sendInputStream()) {
public static Pom getPom(String repo, ArtifactMeta meta) throws IOException, SAXException, URISyntaxException, XMLStreamException {
try (InputStream is = HttpUtils.get(Utils.join("/", repo, meta.getPomPath())).sendInputStream()) {
Document doc = FACTORY.parse(is);
doc.getDocumentElement().normalize();
Pom result = new Pom();
@ -105,24 +93,6 @@ public class MavenApi {
}
}
case "classifier" -> result.classifier = node.getTextContent();
case "versioning" -> {
for (Node node1 : iterable(node.getChildNodes())) {
if (node1.getNodeName().equals("snapshot")) {
String timestamp = null;
String buildNumber = null;
for (Node node2 : iterable(node1.getChildNodes())) {
switch (node2.getNodeName()) {
case "timestamp" -> timestamp = node2.getTextContent();
case "buildNumber" -> buildNumber = node2.getTextContent();
default -> {}
}
}
if (timestamp == null) throw new IOException("Pom snapshots lack timestamp");
if (buildNumber == null) throw new IOException("Pom snapshots lack buildNumber");
result.snapshotVersion = timestamp + '-' + buildNumber;
}
}
}
default -> {}
}
}
@ -178,10 +148,57 @@ public class MavenApi {
return result;
}
private static boolean isWhitespace(Node node) {
if (node.getNodeType() == Node.TEXT_NODE && node.getTextContent().isBlank()) return true;
if (node.getNodeType() == Node.COMMENT_NODE) return true;
return false;
public static ArtifactMeta getMetadata(String repo, String artifact) throws IOException, SAXException, URISyntaxException {
ArtifactMeta sourceMeta = ArtifactMeta.parse(artifact);
try (InputStream is = HttpUtils.get(Utils.join("/", repo, sourceMeta.getMetadataPath())).sendInputStream()) {
Document doc = FACTORY.parse(is);
doc.getDocumentElement().normalize();
ArtifactMeta result = new ArtifactMeta();
if (!"metadata".equals(doc.getDocumentElement().getNodeName())) throw new IOException("Illegal document name");
boolean hasGroupId = false;
boolean hasArtifactId = false;
boolean hasVersion = false;
for (Node node : iterable(doc.getDocumentElement().getChildNodes())) {
switch (node.getNodeName()) {
case "groupId" -> {
hasGroupId = true;
result.groupId = node.getTextContent();
}
case "artifactId" -> {
hasArtifactId = true;
result.artifactId = node.getTextContent();
}
case "version" -> {
hasVersion = true;
result.version = node.getTextContent();
}
case "versioning" -> {
for (Node node1 : iterable(node.getChildNodes())) {
if (node1.getNodeName().equals("snapshot")) {
String timestamp = null;
String buildNumber = null;
for (Node node2 : iterable(node1.getChildNodes())) {
switch (node2.getNodeName()) {
case "timestamp" -> timestamp = node2.getTextContent();
case "buildNumber" -> buildNumber = node2.getTextContent();
default -> {}
}
}
if (timestamp == null) throw new IOException("Pom snapshots lack timestamp");
if (buildNumber == null) throw new IOException("Pom snapshots lack buildNumber");
result.snapshotVersion = timestamp + '-' + buildNumber;
}
}
}
default -> {}
}
}
if (!hasGroupId) throw new IOException("Pom lacks groupId");
if (!hasArtifactId) throw new IOException("Pom lacks artifactId");
if (!hasVersion) throw new IOException("Pom lacks version");
result.classifier = sourceMeta.classifier;
return result;
}
}
private static Iterable<Node> iterable(NodeList list) {
@ -203,47 +220,9 @@ public class MavenApi {
};
}
/**
* Converts an artifact in maven notation to a jar file path. The following are supported:
* - some.base.path:artifact:version -> some/base/path/artifact/version/artifact-version.jar
* - some.base.path:artifact:version:classifier -> some/base/path/artifact/version/artifact-version-classifier.jar
* @param mavenNotation An artifact in maven notation
* @return A file path
*/
public static String mavenNotationToJarPath(String mavenNotation) {
if (Objects.requireNonNull(mavenNotation).isEmpty()) throw new IllegalArgumentException("The notation is empty");
String[] lib = mavenNotation.split(":");
if (lib.length <= 1) throw new IllegalArgumentException("Not in maven notation");
if (lib.length == 2) throw new IllegalArgumentException("Skipping versions is not supported");
if (lib.length >= 5) throw new IllegalArgumentException("Unkown elements in maven notation");
String path = lib[0].replace('.', '/') + '/'; // Base
path += lib[1] + '/'; // Artifact name
path += lib[2] + '/'; // Version
if (lib.length == 3) { // artifact-version.jar
path += lib[1] + '-' + lib[2];
} else { // artifact-version-classifier.jar
path += lib[1] + '-' + lib[2] + "-" + lib[3];
}
return path + ".jar";
}
/**
* Converts an artifact in maven notation to a pom file path. The following are supported:
* - some.base.path:artifact:version -> some/base/path/artifact/version/artifact-version.pom
* - some.base.path:artifact:version:classifier -> some/base/path/artifact/version/artifact-version.pom
* @param mavenNotation An artifact in maven notation
* @return A file path
*/
public static String mavenNotationToPomPath(String mavenNotation) {
if (Objects.requireNonNull(mavenNotation).isEmpty()) throw new IllegalArgumentException("The notation is empty");
String[] lib = mavenNotation.split(":");
if (lib.length <= 1) throw new IllegalArgumentException("Not in maven notation");
if (lib.length == 2) throw new IllegalArgumentException("Skipping versions is not supported");
if (lib.length >= 5) throw new IllegalArgumentException("Unkown elements in maven notation");
String path = lib[0].replace('.', '/') + '/'; // Base
path += lib[1] + '/'; // Artifact name
path += lib[2] + '/'; // Version
path += lib[1] + '-' + lib[2]; // artifact-version
return path + ".pom";
private static boolean isWhitespace(Node node) {
if (node.getNodeType() == Node.TEXT_NODE && node.getTextContent().isBlank()) return true;
if (node.getNodeType() == Node.COMMENT_NODE) return true;
return false;
}
}

View File

@ -0,0 +1,65 @@
package io.gitlab.jfronny.inceptum.common.model.maven;
import io.gitlab.jfronny.inceptum.common.MetaHolder;
import java.nio.file.Path;
import java.util.Objects;
import java.util.regex.Pattern;
public class ArtifactMeta {
public static ArtifactMeta parse(String mavenNotation) {
if (Objects.requireNonNull(mavenNotation).isEmpty()) throw new IllegalArgumentException("The notation is empty");
String[] lib = mavenNotation.split(":");
if (lib.length <= 1) throw new IllegalArgumentException("Not in maven notation");
if (lib.length == 2) throw new IllegalArgumentException("Skipping versions is not supported");
if (lib.length >= 5) throw new IllegalArgumentException("Unkown elements in maven notation");
ArtifactMeta meta = new ArtifactMeta();
meta.groupId = lib[0];
meta.artifactId = lib[1];
meta.version = lib[2];
if (lib.length > 3) meta.classifier = lib[3];
return meta;
}
public String groupId;
public String artifactId;
public String version;
public String classifier;
public String snapshotVersion;
public String getPomPath() {
String path = groupId.replace('.', '/') + '/';
path += artifactId + '/';
path += version + '/';
path += artifactId + '-';
if (snapshotVersion != null) path += version.replace("SNAPSHOT", snapshotVersion);
else path += version;
return path + ".pom";
}
public String getJarPath(boolean respectSnapshotVersion) {
String path = groupId.replace('.', '/') + '/';
path += artifactId + '/';
path += version + '/';
path += artifactId + '-';
if (snapshotVersion != null && respectSnapshotVersion) path += version.replace("SNAPSHOT", snapshotVersion);
else path += version;
if (classifier != null) path += '-' + classifier;
return path + ".jar";
}
public String getMavenNotation() {
String notation = groupId + ':' + artifactId + ':' + version;
if (classifier != null) notation += ':' + classifier;
return notation;
}
public String getMetadataPath() {
return groupId.replace('.', '/') + '/' + artifactId + '/' + version + "/maven-metadata.xml";
}
public Path getLocalPath() {
return MetaHolder.LIBRARIES_DIR.resolve(getJarPath(false));
}
}

View File

@ -6,9 +6,8 @@ public class DependencyNode {
private final String name;
private final Set<DependencyNode> dependencies;
public DependencyNode(Pom pom, Set<DependencyNode> dependencies) {
Objects.requireNonNull(pom);
this.name = pom.groupId + ":" + pom.artifactId + ":" + pom.version;
public DependencyNode(String name, Set<DependencyNode> dependencies) {
this.name = Objects.requireNonNull(name);
this.dependencies = Objects.requireNonNull(dependencies);
}

View File

@ -4,6 +4,7 @@ import io.gitlab.jfronny.gson.compile.util.GList;
import io.gitlab.jfronny.gson.stream.JsonReader;
import io.gitlab.jfronny.inceptum.common.Net;
import io.gitlab.jfronny.inceptum.common.api.MavenApi;
import io.gitlab.jfronny.inceptum.common.model.maven.ArtifactMeta;
import io.gitlab.jfronny.inceptum.launcher.model.fabric.*;
import io.gitlab.jfronny.inceptum.launcher.model.mojang.*;
import io.gitlab.jfronny.inceptum.launcher.util.GameVersionParser;
@ -69,7 +70,7 @@ public class FabricMetaApi {
res.downloads = new VersionInfo.Library.Downloads();
res.downloads.classifiers = null;
res.downloads.artifact = new VersionInfo.Library.Downloads.Artifact();
res.downloads.artifact.path = MavenApi.mavenNotationToJarPath(library.name);
res.downloads.artifact.path = ArtifactMeta.parse(library.name).getJarPath(true);
res.downloads.artifact.size = -1;
res.downloads.artifact.sha1 = null;
res.downloads.artifact.url = library.url + res.downloads.artifact.path;

View File

@ -80,13 +80,13 @@ public class InstanceLauncher {
// Java classpath
StringBuilder classPath = new StringBuilder();
for (ArtifactInfo artifact : VersionInfoLibraryResolver.getRelevant(versionInfo)) {
classPath.append(MetaHolder.LIBRARIES_DIR.resolve(artifact.path).toAbsolutePath());
classPath.append(MetaHolder.LIBRARIES_DIR.resolve(artifact.path));
classPath.append(File.pathSeparatorChar);
}
Path gameJar = MetaHolder.LIBRARIES_DIR.resolve("net/minecraft/" + launchType.name).resolve(versionDataSimple.id + ".jar");
classPath.append(gameJar);
classPath.append(File.pathSeparatorChar);
classPath.append(MetaHolder.LIBRARIES_DIR.resolve(MavenApi.mavenNotationToJarPath(DownloadLibrariesStep.getLaunchWrapperArtifact())));
classPath.append(DownloadLibrariesStep.getLaunchWrapperArtifact().getLocalPath());
// JVM arguments
if (launchType == LaunchType.Client && versionInfo.arguments != null)
args.addAll(parse(versionInfo.arguments.jvm, versionInfo, instance, classPath.toString(), authInfo));
@ -213,7 +213,7 @@ public class InstanceLauncher {
.replace("${auth_player_name}", authInfo.name())
.replace("${version_name}", instance.getGameVersion())
.replace("${game_directory}", instance.path().toString())
.replace("${assets_root}", MetaHolder.ASSETS_DIR.toAbsolutePath().toString())
.replace("${assets_root}", MetaHolder.ASSETS_DIR.toString())
.replace("${assets_index_name}", info.assets)
.replace("${auth_uuid}", authInfo.uuid())
.replace("${auth_access_token}", authInfo.accessToken())
@ -222,7 +222,7 @@ public class InstanceLauncher {
.replace("${resolution_width}", "1920") //TODO has_custom_resolution
.replace("${resolution_height}", "1080") //TODO has_custom_resolution
// jvm args
.replace("${natives_directory}", MetaHolder.NATIVES_DIR.resolve(instance.getGameVersion()).toAbsolutePath().toString())
.replace("${natives_directory}", MetaHolder.NATIVES_DIR.resolve(instance.getGameVersion()).toString())
.replace("${launcher_name}", "Inceptum")
.replace("${launcher_version}", BuildMetadata.VERSION.toString())
.replace("${classpath}", classPath)

View File

@ -3,14 +3,14 @@ package io.gitlab.jfronny.inceptum.launcher.system.setup.steps;
import io.gitlab.jfronny.commons.io.JFiles;
import io.gitlab.jfronny.inceptum.common.*;
import io.gitlab.jfronny.inceptum.common.api.MavenApi;
import io.gitlab.jfronny.inceptum.common.model.maven.ArtifactMeta;
import io.gitlab.jfronny.inceptum.launcher.model.inceptum.ArtifactInfo;
import io.gitlab.jfronny.inceptum.launcher.model.mojang.VersionInfo;
import io.gitlab.jfronny.inceptum.launcher.system.setup.SetupStepInfo;
import io.gitlab.jfronny.inceptum.launcher.system.setup.Step;
import io.gitlab.jfronny.inceptum.launcher.util.*;
import io.gitlab.jfronny.inceptum.launcher.system.setup.SetupStepInfo;
import org.xml.sax.SAXException;
import javax.xml.stream.XMLStreamException;
import java.io.IOException;
import java.net.URISyntaxException;
import java.nio.file.*;
@ -50,17 +50,21 @@ public class DownloadLibrariesStep implements Step {
}
}
String artifact = getLaunchWrapperArtifact();
if (!Files.exists(MetaHolder.LIBRARIES_DIR.resolve(MavenApi.mavenNotationToJarPath(artifact)))) {
ArtifactMeta artifact = getLaunchWrapperArtifact();
if (!Files.exists(artifact.getLocalPath())) {
try {
MavenApi.downloadLibrary(Updater.PROJECT_MAVEN, MavenApi.getPom(Updater.PROJECT_MAVEN, artifact));
} catch (URISyntaxException | XMLStreamException | SAXException e) {
MavenApi.downloadLibrary(Updater.PROJECT_MAVEN, MavenApi.getMetadata(Updater.PROJECT_MAVEN, artifact.getMavenNotation()));
} catch (URISyntaxException | SAXException e) {
throw new IOException("Could not download launchwrapper", e);
}
}
}
public static String getLaunchWrapperArtifact() {
return "io.gitlab.jfronny.inceptum:launchwrapper:" + (BuildMetadata.IS_PUBLIC ? BuildMetadata.VERSION : Updater.getUpdate().version);
public static ArtifactMeta getLaunchWrapperArtifact() {
ArtifactMeta meta = new ArtifactMeta();
meta.groupId = "io.gitlab.jfronny.inceptum";
meta.artifactId = "launchwrapper";
meta.version = BuildMetadata.IS_PUBLIC ? BuildMetadata.VERSION : Updater.getUpdate().version;
return meta;
}
}