Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion flixel/FlxG.hx
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,9 @@ class FlxG
* The HaxeFlixel version, in semantic versioning syntax. Use `Std.string()`
* on it to get a `String` formatted like this: `"HaxeFlixel MAJOR.MINOR.PATCH-COMMIT_SHA"`.
*/
public static final VERSION = new FlxVersion(6, 1, 2);
#if !macro
public static final VERSION:FlxVersion = new flixel.system.FlxAutoVersion<"flixel">();
#end

/**
* Internal tracker for game object.
Expand Down
4 changes: 4 additions & 0 deletions flixel/system/FlxAutoVersion.hx
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
package flixel.system;

@:genericBuild(flixel.system.macros.FlxVersionMacro.build())
class FlxAutoVersion<Const> extends flixel.system.FlxVersion {}
33 changes: 18 additions & 15 deletions flixel/system/FlxVersion.hx
Original file line number Diff line number Diff line change
Expand Up @@ -4,32 +4,35 @@ package flixel.system;
* Helper object for semantic versioning.
* @see http://semver.org/
*/
@:build(flixel.system.macros.FlxGitSHA.buildGitSHA("flixel"))
class FlxVersion
{
public var major(default, null):Int;
public var minor(default, null):Int;
public var patch(default, null):Int;
public final major:Int;
public final minor:Int;
public final patch:Int;
public final prerelease:Null<String>;
public final buildMetadata:Null<String>;
public final sha:Null<String>;

public function new(Major:Int, Minor:Int, Patch:Int)
inline public function new(major:Int, minor:Int, patch:Int, ?prerelease:String, ?buildMetadata:String, ?sha:String)
{
major = Major;
minor = Minor;
patch = Patch;
this.major = major;
this.minor = minor;
this.patch = patch;
this.prerelease = prerelease;
this.buildMetadata = buildMetadata;
this.sha = sha;
}

/**
* Formats the version in the format "HaxeFlixel MAJOR.MINOR.PATCH-COMMIT_SHA",
* e.g. HaxeFlixel 3.0.4.
* If this is a dev version, the git sha is included.
*/
public function toString():String
inline public function toString():String
{
var sha = FlxVersion.sha;
if (sha != "")
{
sha = "@" + sha.substring(0, 7);
}
return 'HaxeFlixel $major.$minor.$patch$sha';
final displaySha = (sha == null ? "" : "@" + sha.substr(0, 7));
final displayPrerelease = (prerelease == null ? "" : '-$prerelease');
final displayMeta = (buildMetadata == null ? "" : '+$buildMetadata');
return 'HaxeFlixel $major.$minor.$patch$displayPrerelease$displayMeta$displaySha';
}
}
4 changes: 2 additions & 2 deletions flixel/system/debug/FlxDebugger.hx
Original file line number Diff line number Diff line change
Expand Up @@ -508,9 +508,9 @@ class FlxDebugger extends openfl.display.Sprite
inline function openGitHub():Void
{
var url = "https://github.com/HaxeFlixel/flixel";
if (FlxVersion.sha != "")
if (FlxG.VERSION.sha != "")
{
url += '/commit/${FlxVersion.sha}';
url += '/commit/${FlxG.VERSION.sha}';
}
FlxG.openURL(url);
}
Expand Down
1 change: 1 addition & 0 deletions flixel/system/macros/FlxGitSHA.hx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ using StringTools;
/**
* Heavily inspired by HaxePunk's HaxeLibInfo.hx
*/
@:deprecated("FlxGitSHA is deprecated, use FlxVersionMacro or FlxAutoVersion, instead")
class FlxGitSHA
{
public static function buildGitSHA(library:String):Array<Field>
Expand Down
158 changes: 158 additions & 0 deletions flixel/system/macros/FlxVersionMacro.hx
Original file line number Diff line number Diff line change
@@ -0,0 +1,158 @@
package flixel.system.macros;

#if macro
import haxe.macro.Context;
import haxe.macro.Expr;
import haxe.macro.Type;
import sys.io.Process;

using StringTools;
using haxe.macro.Tools;
#end

class FlxVersionMacro
{
/**
* Group order: `[ 1 => major, 2 => minor, 3 => patch, 4 => prerelease, 5 => buildmetadata ]`
*/
static public final semver = ~/^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$/;

#if macro
static public function build()
{
switch (Context.getLocalType())
{
case TInst(_.get() => type, [TInst(_.get() => {kind: KExpr(macro $v{(id : String)})}, _)]):
// trace(id, type.name);
return buildType(type, id);
case t:
throw 'Class expected, found ${t}';
}
return null;
}

static function buildType(type:ClassType, id:String):ComplexType
{
final name = 'Version__$id';

// Check whether the generated type already exists
try
{
Context.getType(name);

// Return a `ComplexType` for the generated type
return TPath({pack: [], name: name});
} catch (e) {} // The generated type doesn't exist yet

final ct = Context.getLocalType().toComplexType();
final defineID = id == null ? "log" : '$id.log';
switch ct
{
case TPath(path):
// define the type
// final superClass = type.superClass.t.get();
// final superTp =
// { pack: path.pack
// , name: path.name
// , sub: superClass.name
// #if haxe5
// , pos: path.pos
// #end
// };

if (Context.definedValue(id) == null)
throw 'Haxelib $id not found';

final libVersion = Context.definedValue(id);
if (false == semver.match(libVersion))
throw 'Could not parse lib version "$libVersion"';

final major = Std.parseInt(semver.matched(1));
final minor = Std.parseInt(semver.matched(2));
final patch = Std.parseInt(semver.matched(3));
final prerelease = semver.matched(4);
final buildMetadata = semver.matched(5);

final libPath = getLibraryPath(id);
final sha = getGitSHA(libPath);
final branchRaw = getGitBranch(libPath);
final defaultBranch = getGitDefaultBranch(libPath).split("/").pop();

final branch = branchRaw == defaultBranch ? null : branchRaw;

// final def = macro class $name extends $superTp {
final def = macro class $name extends flixel.system.FlxVersion {
inline public function new()
{
super($v{major}, $v{minor}, $v{patch}, $v{prerelease}, $v{buildMetadata}, $v{sha});
}
}

Context.defineType(def);
return TPath({pack: [], name: name});
case unexpected:
throw 'Unexpected $unexpected';
}
return null;
}

public static function getLibraryPath(library:String):String
{
final output = getProcessOutput("haxelib", ["path", library]);
if (output == null)
throw 'Invalid haxelib: "$library"';

final lines = output.split("\n");

for (i in 1...lines.length)
{
if (lines[i].startsWith('-D $library='))
return lines[i - 1].trim();
}

throw 'Invalid haxelib: "$library"';
}

public static function getGitSHA(path:String):Null<String>
{
final sha = getProcessOutput("git", ["-C", path, "rev-parse", "HEAD"]);
if (sha == null || false == ~/[a-f0-9]{40}/.match(sha))
return null;

return sha;
}

public static function getGitBranch(path:String):Null<String>
{
return getProcessOutput("git", ["-C", path, "rev-parse", "--abbrev-ref", "HEAD"]).trim();
}


public static function getGitDefaultBranch(path:String):Null<String>
{
return getProcessOutput("git", ["-C", path, "symbolic-ref", "--short", "refs/remotes/origin/HEAD"]).trim();
}

public static function getProcessOutput(cmd:String, args:Array<String>):Null<String>
{
try
{
final process = new Process(cmd, args);
var output = "";

try
{
output = process.stdout.readAll().toString();
}
catch (_:Dynamic) {}

process.close();
return output;
}
catch (_:Dynamic)
{
return null;
}
}
#end
}