Improved Version handling for mod info exchange
This commit is contained in:
parent
a43c885db6
commit
7ce674b1f6
4 changed files with 111 additions and 73 deletions
|
@ -17,6 +17,7 @@ import ru.bclib.recipes.CraftingRecipes;
|
||||||
import ru.bclib.registry.BaseBlockEntities;
|
import ru.bclib.registry.BaseBlockEntities;
|
||||||
import ru.bclib.registry.BaseRegistry;
|
import ru.bclib.registry.BaseRegistry;
|
||||||
import ru.bclib.util.Logger;
|
import ru.bclib.util.Logger;
|
||||||
|
import ru.bclib.util.ModUtil;
|
||||||
import ru.bclib.world.generator.BCLibEndBiomeSource;
|
import ru.bclib.world.generator.BCLibEndBiomeSource;
|
||||||
import ru.bclib.world.generator.BCLibNetherBiomeSource;
|
import ru.bclib.world.generator.BCLibNetherBiomeSource;
|
||||||
import ru.bclib.world.generator.GeneratorOptions;
|
import ru.bclib.world.generator.GeneratorOptions;
|
||||||
|
@ -29,6 +30,12 @@ public class BCLib implements ModInitializer {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onInitialize() {
|
public void onInitialize() {
|
||||||
|
System.out.println(ModUtil.convertModVersion("1.2"));
|
||||||
|
System.out.println(ModUtil.convertModVersion("1.2.3"));
|
||||||
|
System.out.println(ModUtil.convertModVersion("1.2.3-4.5"));
|
||||||
|
|
||||||
|
var mods = ModUtil.getMods();
|
||||||
|
mods.entrySet().forEach(e->System.out.println(e.getKey() + ": " + ModUtil.getModVersion(e.getKey()) +" - " + ModUtil.convertModVersion(ModUtil.convertModVersion(e.getValue().getVersion()))));
|
||||||
BaseRegistry.register();
|
BaseRegistry.register();
|
||||||
GeneratorOptions.init();
|
GeneratorOptions.init();
|
||||||
BaseBlockEntities.register();
|
BaseBlockEntities.register();
|
||||||
|
|
|
@ -177,8 +177,6 @@ public class HelloClient extends DataHandler.FromServer {
|
||||||
protected void deserializeIncomingDataOnClient(FriendlyByteBuf buf, PacketSender responseSender) {
|
protected void deserializeIncomingDataOnClient(FriendlyByteBuf buf, PacketSender responseSender) {
|
||||||
//read BCLibVersion (=protocol version)
|
//read BCLibVersion (=protocol version)
|
||||||
bclibVersion = ModUtil.convertModVersion(buf.readInt());
|
bclibVersion = ModUtil.convertModVersion(buf.readInt());
|
||||||
final boolean protocolVersion_0_4_1 = ModUtil.isLargerOrEqualVersion(bclibVersion, "0.4.1");
|
|
||||||
|
|
||||||
|
|
||||||
//read Plugin Versions
|
//read Plugin Versions
|
||||||
modVersion = new ServerModMap();
|
modVersion = new ServerModMap();
|
||||||
|
@ -189,14 +187,8 @@ public class HelloClient extends DataHandler.FromServer {
|
||||||
final int size;
|
final int size;
|
||||||
final boolean canDownload;
|
final boolean canDownload;
|
||||||
//since v0.4.1 we also send the size of the mod-File
|
//since v0.4.1 we also send the size of the mod-File
|
||||||
if (protocolVersion_0_4_1) {
|
size = buf.readInt();
|
||||||
size = buf.readInt();
|
canDownload = buf.readBoolean();
|
||||||
canDownload = buf.readBoolean();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
size = 0;
|
|
||||||
canDownload = true;
|
|
||||||
}
|
|
||||||
modVersion.put(id, new OfferedModInfo(version, size, canDownload));
|
modVersion.put(id, new OfferedModInfo(version, size, canDownload));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -213,15 +205,13 @@ public class HelloClient extends DataHandler.FromServer {
|
||||||
|
|
||||||
autoSynFolders = new ArrayList<>(1);
|
autoSynFolders = new ArrayList<>(1);
|
||||||
//since v0.4.1 we also send the sync folders
|
//since v0.4.1 we also send the sync folders
|
||||||
if (protocolVersion_0_4_1) {
|
final int folderCount = buf.readInt();
|
||||||
final int folderCount = buf.readInt();
|
for (int i = 0; i < folderCount; i++) {
|
||||||
for (int i = 0; i < folderCount; i++) {
|
SyncFolderDescriptor desc = SyncFolderDescriptor.deserialize(buf);
|
||||||
SyncFolderDescriptor desc = SyncFolderDescriptor.deserialize(buf);
|
autoSynFolders.add(desc);
|
||||||
autoSynFolders.add(desc);
|
|
||||||
}
|
|
||||||
|
|
||||||
serverPublishedModInfo = buf.readBoolean();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
serverPublishedModInfo = buf.readBoolean();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Environment(EnvType.CLIENT)
|
@Environment(EnvType.CLIENT)
|
||||||
|
@ -266,7 +256,7 @@ public class HelloClient extends DataHandler.FromServer {
|
||||||
SubFile localSubFile = localDescriptor.getLocalSubFile(subFile.relPath);
|
SubFile localSubFile = localDescriptor.getLocalSubFile(subFile.relPath);
|
||||||
if (localSubFile != null) {
|
if (localSubFile != null) {
|
||||||
//the file exists locally, check if the hashes match
|
//the file exists locally, check if the hashes match
|
||||||
if (!localSubFile.hash.equals(subFile.hash)) {
|
if (true || !localSubFile.hash.equals(subFile.hash)) {
|
||||||
BCLib.LOGGER.info(" * " + subFile.relPath + " (changed)");
|
BCLib.LOGGER.info(" * " + subFile.relPath + " (changed)");
|
||||||
filesToRequest.add(new AutoSyncID.ForDirectFileRequest(desc.folderID, new File(subFile.relPath)));
|
filesToRequest.add(new AutoSyncID.ForDirectFileRequest(desc.folderID, new File(subFile.relPath)));
|
||||||
}
|
}
|
||||||
|
@ -333,11 +323,14 @@ public class HelloClient extends DataHandler.FromServer {
|
||||||
@Environment(EnvType.CLIENT)
|
@Environment(EnvType.CLIENT)
|
||||||
private void processModFileSync(final List<AutoSyncID> filesToRequest, final Set<String> mismatchingMods) {
|
private void processModFileSync(final List<AutoSyncID> filesToRequest, final Set<String> mismatchingMods) {
|
||||||
for (Entry<String, OfferedModInfo> e : modVersion.entrySet()) {
|
for (Entry<String, OfferedModInfo> e : modVersion.entrySet()) {
|
||||||
final String localVersion = ModUtil.getModVersion(e.getKey());
|
final String localVersion = ModUtil.convertModVersion(ModUtil.convertModVersion(ModUtil.getModVersion(e.getKey())));
|
||||||
final OfferedModInfo serverInfo = e.getValue();
|
final OfferedModInfo serverInfo = e.getValue();
|
||||||
final boolean requestMod = !serverInfo.version.equals(localVersion) && serverInfo.size > 0 && serverInfo.canDownload;
|
|
||||||
|
|
||||||
BCLib.LOGGER.info(" - " + e.getKey() + " (client=" + localVersion + ", server=" + serverInfo.version + ", size=" + PathUtil.humanReadableFileSize(serverInfo.size) + (requestMod ? ", requesting" : "") + (serverInfo.canDownload ? "" :", not offered")+ ")");
|
ModInfo nfo = ModUtil.getModInfo(e.getKey());
|
||||||
|
final boolean clientOnly = nfo!=null && nfo.metadata.getEnvironment()==ModEnvironment.CLIENT;
|
||||||
|
final boolean requestMod = !clientOnly && !serverInfo.version.equals(localVersion) && serverInfo.size > 0 && serverInfo.canDownload;
|
||||||
|
|
||||||
|
BCLib.LOGGER.info(" - " + e.getKey() + " (client=" + localVersion + ", server=" + serverInfo.version + ", size=" + PathUtil.humanReadableFileSize(serverInfo.size) + (requestMod ? ", requesting" : "") + (serverInfo.canDownload ? "" :", not offered") + (clientOnly?", client only":"")+ ")");
|
||||||
if (requestMod) {
|
if (requestMod) {
|
||||||
filesToRequest.add(new AutoSyncID.ForModFileRequest(e.getKey(), serverInfo.version));
|
filesToRequest.add(new AutoSyncID.ForModFileRequest(e.getKey(), serverInfo.version));
|
||||||
}
|
}
|
||||||
|
|
|
@ -76,6 +76,7 @@ public class ModListScreen extends BCLibScreen {
|
||||||
final int STATE_OK = 6;
|
final int STATE_OK = 6;
|
||||||
final int STATE_SERVER_MISSING_CLIENT_MOD = 5;
|
final int STATE_SERVER_MISSING_CLIENT_MOD = 5;
|
||||||
final int STATE_MISSING_NOT_OFFERED = 4;
|
final int STATE_MISSING_NOT_OFFERED = 4;
|
||||||
|
final int STATE_VERSION_CLIENT_ONLY = 7;
|
||||||
final int STATE_VERSION_NOT_OFFERED = 3;
|
final int STATE_VERSION_NOT_OFFERED = 3;
|
||||||
final int STATE_VERSION = 2;
|
final int STATE_VERSION = 2;
|
||||||
final int STATE_SERVER_MISSING = 1;
|
final int STATE_SERVER_MISSING = 1;
|
||||||
|
@ -114,7 +115,10 @@ public class ModListScreen extends BCLibScreen {
|
||||||
final String modVer = data.version();
|
final String modVer = data.version();
|
||||||
final int size = data.size();
|
final int size = data.size();
|
||||||
if (!modVer.equals(mod.getVersion())) {
|
if (!modVer.equals(mod.getVersion())) {
|
||||||
state = data.canDownload()?STATE_VERSION:STATE_VERSION_NOT_OFFERED;
|
if (mod.metadata.getEnvironment() == ModEnvironment.CLIENT)
|
||||||
|
state = STATE_VERSION_CLIENT_ONLY;
|
||||||
|
else
|
||||||
|
state = data.canDownload()?STATE_VERSION:STATE_VERSION_NOT_OFFERED;
|
||||||
serverVersion = modVer;
|
serverVersion = modVer;
|
||||||
serverSize = size;
|
serverSize = size;
|
||||||
}
|
}
|
||||||
|
@ -150,10 +154,12 @@ public class ModListScreen extends BCLibScreen {
|
||||||
|
|
||||||
int color = GridLayout.COLOR_RED;
|
int color = GridLayout.COLOR_RED;
|
||||||
final String typeText;
|
final String typeText;
|
||||||
if (state==STATE_VERSION || state==STATE_VERSION_NOT_OFFERED) {
|
if (state==STATE_VERSION || state==STATE_VERSION_NOT_OFFERED || state==STATE_VERSION_CLIENT_ONLY) {
|
||||||
typeText = "[VERSION]";
|
typeText = "[VERSION]";
|
||||||
if (state == STATE_VERSION_NOT_OFFERED) {
|
if (state == STATE_VERSION_NOT_OFFERED) {
|
||||||
color = GridLayout.COLOR_YELLOW;
|
color = GridLayout.COLOR_YELLOW;
|
||||||
|
} else if (state == STATE_VERSION_CLIENT_ONLY) {
|
||||||
|
color = GridLayout.COLOR_DARK_GREEN;
|
||||||
}
|
}
|
||||||
} else if (state==STATE_MISSING || state==STATE_MISSING_NOT_OFFERED) {
|
} else if (state==STATE_MISSING || state==STATE_MISSING_NOT_OFFERED) {
|
||||||
typeText = "[MISSING]";
|
typeText = "[MISSING]";
|
||||||
|
|
|
@ -62,53 +62,31 @@ public class ModUtil {
|
||||||
|
|
||||||
mods = new HashMap<>();
|
mods = new HashMap<>();
|
||||||
org.apache.logging.log4j.Logger logger = LogManager.getFormatterLogger("BCLib|ModLoader");
|
org.apache.logging.log4j.Logger logger = LogManager.getFormatterLogger("BCLib|ModLoader");
|
||||||
PathUtil.fileWalker(PathUtil.MOD_FOLDER.toFile(), false, (file -> {
|
PathUtil.fileWalker(PathUtil.MOD_FOLDER.toFile(), false, (ModUtil::accept));
|
||||||
try {
|
|
||||||
URI uri = URI.create("jar:" + file.toUri());
|
|
||||||
FileSystem fs = FileSystems.getFileSystem(uri);
|
|
||||||
if (fs!=null) {
|
|
||||||
try {
|
|
||||||
Path modMetaFile = fs.getPath("fabric.mod.json");
|
|
||||||
if (modMetaFile != null) {
|
|
||||||
try (InputStream is = Files.newInputStream(modMetaFile)) {
|
|
||||||
//ModMetadata mc = ModMetadataParser.parseMetadata(is, uri.toString(), new LinkedList<String>());
|
|
||||||
ModMetadata mc = readJSON(is, uri.toString());
|
|
||||||
if (mc!=null){
|
|
||||||
mods.put(mc.getId(), new ModInfo(mc, file));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
|
||||||
BCLib.LOGGER.error(e.getMessage());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception e) {
|
|
||||||
BCLib.LOGGER.error(e.getMessage());
|
|
||||||
}
|
|
||||||
}));
|
|
||||||
|
|
||||||
return mods;
|
return mods;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static ModMetadata readJSON(InputStream is, String sourceFile) throws IOException {
|
private static ModMetadata readJSON(InputStream is, String sourceFile) throws IOException {
|
||||||
try (com.google.gson.stream.JsonReader reader = new JsonReader(new InputStreamReader(is, StandardCharsets.UTF_8))) {
|
try (com.google.gson.stream.JsonReader reader = new JsonReader(new InputStreamReader(is, StandardCharsets.UTF_8))) {
|
||||||
JsonObject data = new JsonParser().parse(reader).getAsJsonObject();
|
JsonObject data = new JsonParser().parse(reader)
|
||||||
|
.getAsJsonObject();
|
||||||
Version ver;
|
Version ver;
|
||||||
try {
|
try {
|
||||||
ver = new SemanticVersionImpl(data.get("version").getAsString(), false);
|
ver = new SemanticVersionImpl(data.get("version")
|
||||||
|
.getAsString(), false);
|
||||||
}
|
}
|
||||||
catch (VersionParsingException e) {
|
catch (VersionParsingException e) {
|
||||||
BCLib.LOGGER.error("Unable to parse Version in " + sourceFile);
|
BCLib.LOGGER.error("Unable to parse Version in " + sourceFile);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (data.get("id") == null){
|
if (data.get("id") == null) {
|
||||||
BCLib.LOGGER.error("Unable to read ID in " + sourceFile);
|
BCLib.LOGGER.error("Unable to read ID in " + sourceFile);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (data.get("name") == null){
|
if (data.get("name") == null) {
|
||||||
BCLib.LOGGER.error("Unable to read name in " + sourceFile);
|
BCLib.LOGGER.error("Unable to read name in " + sourceFile);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -118,6 +96,7 @@ public class ModUtil {
|
||||||
public Version getVersion() {
|
public Version getVersion() {
|
||||||
return ver;
|
return ver;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getType() {
|
public String getType() {
|
||||||
return "fabric";
|
return "fabric";
|
||||||
|
@ -125,7 +104,8 @@ public class ModUtil {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getId() {
|
public String getId() {
|
||||||
return data.get("id").getAsString();
|
return data.get("id")
|
||||||
|
.getAsString();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -136,35 +116,44 @@ public class ModUtil {
|
||||||
@Override
|
@Override
|
||||||
public ModEnvironment getEnvironment() {
|
public ModEnvironment getEnvironment() {
|
||||||
JsonElement env = data.get("environment");
|
JsonElement env = data.get("environment");
|
||||||
if (env==null) {
|
if (env == null) {
|
||||||
BCLib.LOGGER.warning("No environment specified in " + sourceFile);
|
BCLib.LOGGER.warning("No environment specified in " + sourceFile);
|
||||||
//return ModEnvironment.UNIVERSAL;
|
//return ModEnvironment.UNIVERSAL;
|
||||||
}
|
}
|
||||||
final String environment = env==null?"":env.getAsString().toLowerCase(Locale.ROOT);
|
final String environment = env == null ? "" : env.getAsString()
|
||||||
|
.toLowerCase(Locale.ROOT);
|
||||||
|
|
||||||
if (environment.isEmpty() || environment.equals("*") || environment.equals("common")) {
|
if (environment.isEmpty() || environment.equals("*") || environment.equals("\"*\"") || environment.equals("common")) {
|
||||||
JsonElement entrypoints = data.get("entrypoints");
|
JsonElement entrypoints = data.get("entrypoints");
|
||||||
boolean hasClient = true;
|
boolean hasClient = true;
|
||||||
|
|
||||||
//check if there is an actual client entrypoint
|
//check if there is an actual client entrypoint
|
||||||
if (entrypoints!=null && entrypoints.isJsonObject()){
|
if (entrypoints != null && entrypoints.isJsonObject()) {
|
||||||
JsonElement client = entrypoints.getAsJsonObject().get("client");
|
JsonElement client = entrypoints.getAsJsonObject()
|
||||||
if (client!=null && client.isJsonArray()){
|
.get("client");
|
||||||
hasClient = client.getAsJsonArray().size() > 0;
|
if (client != null && client.isJsonArray()) {
|
||||||
} else if (client==null || !client.isJsonPrimitive()){
|
hasClient = client.getAsJsonArray()
|
||||||
|
.size() > 0;
|
||||||
|
}
|
||||||
|
else if (client == null || !client.isJsonPrimitive()) {
|
||||||
hasClient = false;
|
hasClient = false;
|
||||||
} else if (!client.getAsJsonPrimitive().isString()){
|
}
|
||||||
|
else if (!client.getAsJsonPrimitive()
|
||||||
|
.isString()) {
|
||||||
hasClient = false;
|
hasClient = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hasClient == false) return ModEnvironment.SERVER;
|
//if (hasClient == false) return ModEnvironment.SERVER;
|
||||||
return ModEnvironment.UNIVERSAL;
|
return ModEnvironment.UNIVERSAL;
|
||||||
} else if (environment.equals("client")) {
|
}
|
||||||
|
else if (environment.equals("client")) {
|
||||||
return ModEnvironment.CLIENT;
|
return ModEnvironment.CLIENT;
|
||||||
} else if (environment.equals("server")) {
|
}
|
||||||
|
else if (environment.equals("server")) {
|
||||||
return ModEnvironment.SERVER;
|
return ModEnvironment.SERVER;
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
BCLib.LOGGER.error("Unable to read environment in " + sourceFile);
|
BCLib.LOGGER.error("Unable to read environment in " + sourceFile);
|
||||||
return ModEnvironment.UNIVERSAL;
|
return ModEnvironment.UNIVERSAL;
|
||||||
}
|
}
|
||||||
|
@ -201,7 +190,8 @@ public class ModUtil {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getName() {
|
public String getName() {
|
||||||
return data.get("name").getAsString();
|
return data.get("name")
|
||||||
|
.getAsString();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -325,13 +315,16 @@ public class ModUtil {
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
int res = 0;
|
int res = 0;
|
||||||
final String semanticVersionPattern = "(\\d+)\\.(\\d+)\\.(\\d+)\\D*";
|
final String semanticVersionPattern = "(\\d+)\\.(\\d+)(\\.(\\d+))?\\D*";
|
||||||
final Matcher matcher = Pattern.compile(semanticVersionPattern)
|
final Matcher matcher = Pattern.compile(semanticVersionPattern)
|
||||||
.matcher(version);
|
.matcher(version);
|
||||||
if (matcher.find()) {
|
if (matcher.find()) {
|
||||||
if (matcher.groupCount() > 0) res = (Integer.parseInt(matcher.group(1)) & 0xFF) << 22;
|
if (matcher.groupCount() > 0)
|
||||||
if (matcher.groupCount() > 1) res |= (Integer.parseInt(matcher.group(2)) & 0xFF) << 14;
|
res = matcher.group(1) == null ? 0 : ((Integer.parseInt(matcher.group(1)) & 0xFF) << 22);
|
||||||
if (matcher.groupCount() > 2) res |= Integer.parseInt(matcher.group(3)) & 0x3FFF;
|
if (matcher.groupCount() > 1)
|
||||||
|
res |= matcher.group(2) == null ? 0 : ((Integer.parseInt(matcher.group(2)) & 0xFF) << 14);
|
||||||
|
if (matcher.groupCount() > 3)
|
||||||
|
res |= matcher.group(4) == null ? 0 : Integer.parseInt(matcher.group(4)) & 0x3FFF;
|
||||||
}
|
}
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
|
@ -376,6 +369,43 @@ public class ModUtil {
|
||||||
return convertModVersion(v1) >= convertModVersion(v2);
|
return convertModVersion(v1) >= convertModVersion(v2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void accept(Path file) {
|
||||||
|
try {
|
||||||
|
URI uri = URI.create("jar:" + file.toUri());
|
||||||
|
System.out.println(uri);
|
||||||
|
|
||||||
|
FileSystem fs;
|
||||||
|
try {
|
||||||
|
fs = FileSystems.getFileSystem(uri);
|
||||||
|
}
|
||||||
|
catch (Exception e) {
|
||||||
|
fs = FileSystems.newFileSystem(file);
|
||||||
|
}
|
||||||
|
if (fs != null) {
|
||||||
|
try {
|
||||||
|
Path modMetaFile = fs.getPath("fabric.mod.json");
|
||||||
|
if (modMetaFile != null) {
|
||||||
|
try (InputStream is = Files.newInputStream(modMetaFile)) {
|
||||||
|
//ModMetadata mc = ModMetadataParser.parseMetadata(is, uri.toString(), new LinkedList<String>());
|
||||||
|
ModMetadata mc = readJSON(is, uri.toString());
|
||||||
|
if (mc != null) {
|
||||||
|
mods.put(mc.getId(), new ModInfo(mc, file));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception e) {
|
||||||
|
BCLib.LOGGER.error("Error for " + uri + ": " + e.toString());
|
||||||
|
}
|
||||||
|
fs.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception e) {
|
||||||
|
BCLib.LOGGER.error("Error for " + file.toUri() + ": " + e.toString());
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static class ModInfo {
|
public static class ModInfo {
|
||||||
public final ModMetadata metadata;
|
public final ModMetadata metadata;
|
||||||
public final Path jarPath;
|
public final Path jarPath;
|
||||||
|
@ -416,7 +446,9 @@ public class ModUtil {
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getVersion() {
|
public String getVersion() {
|
||||||
if (metadata == null) return "0.0.0";
|
if (metadata == null) {
|
||||||
|
return "0.0.0";
|
||||||
|
}
|
||||||
return versionToString(metadata.getVersion());
|
return versionToString(metadata.getVersion());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue