package jaci.openrio.toast.lib;
import jaci.openrio.toast.core.ToastBootstrap;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* The versioning manager for Toast. This allows for modules to easily parse what version of Toast is running
* on the Robot.
*
* Keep in mind this isn't enforced in {@link jaci.openrio.toast.lib.module.ToastModule}, since some modules
* may choose to respect an 'irregular' version formatting scheme
*
* @author Jaci
*/
public class Version implements Comparable<Version> {
static String version = "1.3.0";
static Version vers;
static boolean known = false;
static Pattern versionPattern = Pattern.compile("(\\d*).(\\d*).(\\d*)(-(\\d*)([a-z]))?");
static String full_commit_hash;
static String short_commit_hash;
/**
* Initialize the Version. This reads from the toast.version file in the jar file, parsing the Regex and validating the Toast
* File's Version for modules to read.
*/
public static void init() {
try {
BufferedReader reader = new BufferedReader(new InputStreamReader(ClassLoader.getSystemClassLoader().getResourceAsStream("assets/toast/toast.version")));
version = reader.readLine();
reader.close();
ToastBootstrap.toastLogger.info("Toast Version: " + version);
known = true;
vers = new Version(version);
reader = new BufferedReader(new InputStreamReader(ClassLoader.getSystemClassLoader().getResourceAsStream("assets/toast/toast.git_info")));
full_commit_hash = reader.readLine();
short_commit_hash = reader.readLine();
reader.close();
ToastBootstrap.toastLogger.info("Toast Commit Hash: " + short_commit_hash);
} catch (Exception e) {
ToastBootstrap.toastLogger.error("Could not retrieve Toast Version or Git Hash.");
}
}
/**
* Returns true if we know what version Toast is, or false if we don't. This will only return false if
* there was an error reading the /assets/toast/toast.version file.
*/
public static boolean versionKnown() {
return known;
}
/**
* Get Toast's current version.
*/
public static Version version() {
return vers;
}
/**
* Get the full Git commit hash of the Toast build
*/
public static String getCommitHash() {
return full_commit_hash;
}
/**
* Get the short Git commit hash of the Toast build
*/
public static String getShortCommitHash() {
return short_commit_hash;
}
/**
* Returns true if 'version' is equal to or newer than 'required'
*/
public static boolean requireOrNewer(Version version, Version required) {
int compare = version.compareTo(required);
return compare == 0 || compare == 1;
}
// -- inst -- //
String versString;
int major;
int minor;
int build;
boolean preRelease;
char prereleaseType;
int prebuild;
boolean parsed;
/**
* Create a new Version and Parse it. The version object should be in the form
* 'major.minor.build[-prebuild]', with everything in square brackets being
* optional. 'prebuild' should consist of a build number following a letter
* regarding the build type (A for Alpha, B for Beta, etc).
*
* e.g.
* "1.3.0"
* "1.3.0-10a"
*/
public Version(String versionString) {
versString = versionString;
parsed = false;
parse();
}
/**
* Parse the Version String with the Regex pattern
*/
public void parse() {
Matcher matcher = versionPattern.matcher(versString);
int c = matcher.groupCount();
if (c < 3 || !matcher.matches()) throw new VersionFormatException();
major = Integer.parseInt(matcher.group(1));
minor = Integer.parseInt(matcher.group(2));
build = Integer.parseInt(matcher.group(3));
if (c == 6 && matcher.group(6) != null) {
preRelease = true;
prereleaseType = matcher.group(6).charAt(0);
prebuild = Integer.parseInt(matcher.group(5));
}
parsed = true;
}
/**
* Get the parsed version as a formatted string
*/
public String get() {
if (!preRelease)
return String.format("%s.%s.%s", major, minor, build);
else
return String.format("%s.%s.%s-%s%s", major, minor, build, prebuild, prereleaseType);
}
/**
* Get the raw version passed into the constructor (unparsed)
*/
public String raw() {
return versString;
}
/**
* Convert the Version to String Format, for use in printing to the console or other implementations
*/
public String toString() {
if (!parsed)
return "Version[unknown]";
if (!preRelease)
return String.format("Version[%s.%s.%s]", major, minor, build);
else
return String.format("Version[%s.%s.%s-%s%s]", major, minor, build, prebuild, prereleaseType);
}
/**
* Compare 2 versions against each other.
* @return 0 if versions are equal, -1 if older than 'o', 1 if newer than 'o'
*/
@Override
public int compareTo(Version o) {
if (equals(o)) return 0;
if (o.major != major)
return o.major > major ? -1 : 1;
if (o.minor != minor)
return o.minor > minor ? -1 : 1;
if (o.build != build)
return o.build > build ? -1 : 1;
if (o.preRelease && preRelease) {
if (o.prebuild == prebuild)
return o.prereleaseType > prereleaseType ? -1 : 1;
return o.prebuild > prebuild ? -1 : 1;
} else if (o.preRelease)
return 1;
else if (preRelease)
return -1;
return 0;
}
/**
* Returns true if this version is newer than 'o'
*/
public boolean newerThan(Version o) {
return compareTo(o) == 1;
}
/**
* Returns true if this version is older than 'o'
*/
public boolean olderThan(Version o) {
return compareTo(o) == -1;
}
/**
* Returns true if versions are equal
*/
public boolean equals(Version o) {
return o.preRelease == preRelease && !(o.major != major || o.minor != minor || o.build != build) && (!preRelease || o.prereleaseType == prereleaseType && o.prebuild == prebuild);
}
/**
* Thrown if a supplied version does not pass the Regex Matcher (is malformed).
* @see {@link jaci.openrio.toast.lib.Version#Version(String)}
*/
public static class VersionFormatException extends RuntimeException { }
}