diff --git a/build.gradle b/build.gradle index d69d6a8..7ed8c0e 100644 --- a/build.gradle +++ b/build.gradle @@ -3,8 +3,11 @@ */ plugins { - // Apply the java-library plugin to add support for Java Library - id 'java-library' + id 'java' + + // GrGit + // A JGit wrapper for Groovy used to access git commit info + id 'org.ajoberstar.grgit' version '4.1.1' /* * Uncomment the following line to enable the Eclipse plugin. @@ -237,12 +240,44 @@ task specifyLocalManifest { if (classPath.size() == configurations.runtimeClasspath.size()) { println "Nothing removed from JAR classpath" } - + + def version = "dev"; + def commit = "-"; + def branch = "-"; + def buildId = project.findProperty('buildId') ?: "-"; + + try { + def git = org.ajoberstar.grgit.Grgit.open() + def head = git.head() + + commit = head.id + branch = git.branch.current().name + + def newestTag = git.tag.list().findAll { it.commit == head } ?.max { it.dateTime } ?.name + if (newestTag != null) { + version = newestTag; + } else if (project.hasProperty('buildId')) { + version = project.buildId; + } else { + version = head.dateTime.format(java.time.format.DateTimeFormatter.ISO_LOCAL_DATE); + } + } catch (org.eclipse.jgit.errors.RepositoryNotFoundException e) { + println "No Git repository found in project root" + } + jar { manifest { attributes( "Main-Class": "ru.windcorp.progressia.client.ProgressiaClientMain", - "Class-Path": configurations.runtimeClasspath.collect { "lib/" + it.getName() } .findAll { isDependencyRequested(it) } .join(' ') + "Class-Path": configurations.runtimeClasspath.collect { "lib/" + it.getName() } .findAll { isDependencyRequested(it) } .join(' '), + + "Specification-Title": "Progressia", + + "Implementation-Title": "Progressia", + "Implementation-Version": version, + "Implementation-Version-Git-Commit": commit, + "Implementation-Version-Git-Branch": branch, + "Implementation-Version-BuildId": buildId, ) } } diff --git a/src/main/java/ru/windcorp/progressia/Progressia.java b/src/main/java/ru/windcorp/progressia/Progressia.java index db899ea..45d64c6 100644 --- a/src/main/java/ru/windcorp/progressia/Progressia.java +++ b/src/main/java/ru/windcorp/progressia/Progressia.java @@ -15,9 +15,180 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - + package ru.windcorp.progressia; +import java.io.IOException; +import java.net.URL; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Enumeration; +import java.util.jar.Attributes; +import java.util.jar.Manifest; + +import org.apache.logging.log4j.LogManager; + +import ru.windcorp.progressia.common.util.crash.CrashReports; + +/** + * A class providing access to build metadata. + */ public class Progressia { + private static final String NAME = "Progressia"; + private static String version; + private static String gitCommit; + private static String gitBranch; + private static String buildId; + + static { + try { + Manifest manifest = findManifest(); + + if (manifest == null) { + setDevelopmentMetadata(); + LogManager.getLogger().info( + "Manifest with Specification-Title not found. " + + "Either you are in a development environment or something has gone horribly wrong with classloaders." + ); + } else { + fillMetadata(manifest); + } + } catch (Throwable t) { + CrashReports.crash(t, "Something went wrong while loading metadata"); + } + } + + private static Manifest findManifest() { + try { + Enumeration resources = Progressia.class.getClassLoader().getResources("META-INF/MANIFEST.MF"); + Collection exceptions = new ArrayList<>(); + + while (resources.hasMoreElements()) { + URL url = resources.nextElement(); + + try { + + Manifest manifest = new Manifest(url.openStream()); + Attributes mainAttributes = manifest.getMainAttributes(); + if (NAME.equals(mainAttributes.getValue("Specification-Title"))) { + return manifest; + } + + } catch (IOException e) { + exceptions.add(e); + } + } + + if (exceptions.isEmpty()) { + return null; + } + + IOException scapegoat = null; + for (IOException e : exceptions) { + if (scapegoat == null) { + scapegoat = e; + } else { + scapegoat.addSuppressed(e); + } + } + + throw CrashReports.report(scapegoat, "Could not read manifest"); + } catch (IOException e) { + throw CrashReports.report(e, "Could not read manifest"); + } + } + + private static void setDevelopmentMetadata() { + version = "dev"; + gitCommit = "-"; + gitBranch = "-"; + buildId = "-"; + } + + private static void fillMetadata(Manifest manifest) { + version = getAttributeOrCrash(manifest, "Implementation-Version"); + gitCommit = getAttributeOrCrash(manifest, "Implementation-Version-Git-Commit"); + gitBranch = getAttributeOrCrash(manifest, "Implementation-Version-Git-Branch"); + buildId = getAttributeOrCrash(manifest, "Implementation-Version-BuildId"); + } + + private static String getAttributeOrCrash(Manifest manifest, String key) { + String result = manifest.getMainAttributes().getValue(key); + if (result == null) { + throw CrashReports.report(null, "Manifest exists but attribute " + key + " not found"); + } + return result; + } + + public static String getName() { + return NAME; + } + + /** + * Returns the version of the game as a String. Version data is retrieved + * from a {@code META-INF/MANIFEST.MF} file located in the main JAR. Version + * format depends on way the game was built: + *
    + *
  • dev if no matching manifest was found, e.g. when launching from an IDE
  • + *
  • The value of Implementation-Version specified in the manifest: + *
      + *
    • [Stage-]Major.Minor.Patch, e.g. alpha-0.3.2 or 1.4.2, for released versions
    • + *
    • BuildId, e.g. WJ7, for snapshots built by automation systems
    • + *
    • YYYY-MM-DD, e.g. 2021-12-32, for snapshots built manually
    • + *
    + *
  • + *
+ * + * @return the version + */ + public static String getVersion() { + return version; + } + + public static String getFullerVersion() { + if (isDefaultGitBranch() || "-".equals(gitBranch)) { + return version; + } else { + return String.format("%s/%s", version, gitBranch); + } + } + + /** + * @return the buildId or "-" + */ + public static String getBuildId() { + return buildId; + } + + /** + * @return the Git commit or "-" + */ + public static String getGitCommit() { + return gitCommit; + } + + public static String getGitCommitShort() { + if (gitCommit == null || "-".equals(gitCommit)) { + return gitCommit; + } + + return gitCommit.substring(0, Math.min(7, gitCommit.length())); + } + + /** + * @return the Git branch or "-" + */ + public static String getGitBranch() { + return gitBranch; + } + + public static boolean isDefaultGitBranch() { + return "master".equals(gitBranch) || "main".equals(gitBranch); + } + + public static String getFullVersion() { + return String.format("%s/%s/%s/%s", version, gitBranch, getGitCommitShort(), buildId); + } + } diff --git a/src/main/java/ru/windcorp/progressia/ProgressiaLauncher.java b/src/main/java/ru/windcorp/progressia/ProgressiaLauncher.java index 099d378..2190677 100644 --- a/src/main/java/ru/windcorp/progressia/ProgressiaLauncher.java +++ b/src/main/java/ru/windcorp/progressia/ProgressiaLauncher.java @@ -18,6 +18,8 @@ package ru.windcorp.progressia; +import org.apache.logging.log4j.LogManager; + import ru.windcorp.progressia.client.graphics.GUI; import ru.windcorp.progressia.common.util.crash.CrashReports; import ru.windcorp.progressia.common.util.crash.analyzers.OutOfMemoryAnalyzer; @@ -32,6 +34,8 @@ public class ProgressiaLauncher { public static void launch(String[] args, Proxy proxy) { arguments = args.clone(); setupCrashReports(); + + LogManager.getRootLogger().info("Launching " + Progressia.getName() + " version " + Progressia.getFullVersion()); proxy.initialize(); ProgressiaLauncher.proxy = proxy; @@ -44,6 +48,7 @@ public class ProgressiaLauncher { private static void setupCrashReports() { // Context providers + CrashReports.registerProvider(new VersionProvider()); CrashReports.registerProvider(new OSContextProvider()); CrashReports.registerProvider(new RAMContextProvider()); CrashReports.registerProvider(new JavaVersionContextProvider()); diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/backend/LWJGLInitializer.java b/src/main/java/ru/windcorp/progressia/client/graphics/backend/LWJGLInitializer.java index 9bc280e..cff7421 100644 --- a/src/main/java/ru/windcorp/progressia/client/graphics/backend/LWJGLInitializer.java +++ b/src/main/java/ru/windcorp/progressia/client/graphics/backend/LWJGLInitializer.java @@ -26,6 +26,7 @@ import org.lwjgl.opengl.GL; import com.google.common.eventbus.Subscribe; +import ru.windcorp.progressia.Progressia; import ru.windcorp.progressia.client.graphics.GUI; import ru.windcorp.progressia.client.graphics.input.FrameResizeEvent; import ru.windcorp.progressia.client.graphics.input.InputEvent; @@ -62,8 +63,8 @@ class LWJGLInitializer { glfwWindowHint(GLFW_RESIZABLE, GLFW_TRUE); glfwWindowHint(GLFW_FOCUSED, GLFW_TRUE); glfwWindowHint(GLFW_MAXIMIZED, GLFW_TRUE); - - long handle = glfwCreateWindow(900, 900, "ProgressiaTest", NULL, NULL); + + long handle = glfwCreateWindow(800, 600, Progressia.getName() + " " + Progressia.getFullerVersion(), NULL, NULL); // TODO Check that handle != NULL diff --git a/src/main/java/ru/windcorp/progressia/common/util/crash/providers/VersionProvider.java b/src/main/java/ru/windcorp/progressia/common/util/crash/providers/VersionProvider.java new file mode 100644 index 0000000..f53d26e --- /dev/null +++ b/src/main/java/ru/windcorp/progressia/common/util/crash/providers/VersionProvider.java @@ -0,0 +1,40 @@ +/* + * Progressia + * Copyright (C) 2020-2021 Wind Corporation and contributors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package ru.windcorp.progressia.common.util.crash.providers; + +import java.util.Map; + +import ru.windcorp.progressia.Progressia; +import ru.windcorp.progressia.common.util.crash.ContextProvider; + +public class VersionProvider implements ContextProvider { + + @Override + public void provideContext(Map output) { + output.put("Version", Progressia.getVersion()); + output.put("Git commit", Progressia.getGitCommit()); + output.put("Git branch", Progressia.getGitBranch()); + output.put("Build ID", Progressia.getBuildId()); + } + + @Override + public String getName() { + return "Version Provider"; + } + +} diff --git a/src/main/java/ru/windcorp/progressia/test/LayerAbout.java b/src/main/java/ru/windcorp/progressia/test/LayerAbout.java index fae2357..0011985 100644 --- a/src/main/java/ru/windcorp/progressia/test/LayerAbout.java +++ b/src/main/java/ru/windcorp/progressia/test/LayerAbout.java @@ -18,6 +18,7 @@ package ru.windcorp.progressia.test; +import ru.windcorp.progressia.Progressia; import ru.windcorp.progressia.client.graphics.Colors; import ru.windcorp.progressia.client.graphics.font.Font; import ru.windcorp.progressia.client.graphics.font.Typeface; @@ -50,7 +51,7 @@ public class LayerAbout extends GUILayer { new Label( "Version", font, - new MutableStringLocalized("LayerAbout.Version").format("pre-alpha 3") + new MutableStringLocalized("LayerAbout.Version").format(Progressia.getFullerVersion()) ) );