Skip to content

Instantly share code, notes, and snippets.

@maul-esel
Created June 19, 2012 18:28
Show Gist options
  • Save maul-esel/2955747 to your computer and use it in GitHub Desktop.
Save maul-esel/2955747 to your computer and use it in GitHub Desktop.
semver AHK lib
semver_validate(version)
{
return !!RegExMatch(version, "^(\d+)\.(\d+)\.(\d+)(\-([0-9A-Za-z\-]+\.)*[0-9A-Za-z\-]+)?(\+([0-9A-Za-z\-]+\.)*[0-9A-Za-z\-]+)?$")
}
semver_parts(version, byRef out_major, byRef out_minor, byRef out_patch, byRef out_prerelease, byRef out_build)
{
return !!RegExMatch(version, "^(?P<major>\d+)\.(?P<minor>\d+)\.(?P<patch>\d+)(\-(?P<prerelease>([0-9A-Za-z\-]+\.)*([0-9A-Za-z\-]+)))?(\+?(?P<build>([0-9A-Za-z\-]+\.)*([0-9A-Za-z\-]+)))?$", out_)
}
semver_compare(version1, version2)
{
if (!semver_parts(version1, maj1, min1, pat1, pre1, bld1))
throw Exception("Invalid version: " version1)
if (!semver_parts(version2, maj2, min2, pat2, pre2, bld2))
throw Exception("Invalid version: " version2)
for each, part in ["maj", "min", "pat"]
{
%part%1 += 0, %part%2 += 0
if (%part%1 < %part%2)
return -1
else if (%part%1 > %part%2)
return +1
}
for each, part in ["pre", "bld"] ; { "pre" : 1, "bld" : -1 }
{
if (%part%1 && %part%2)
{
StringSplit part1_, %part%1, .
StringSplit part2_, %part%2, .
Loop % part1_0 < part2_0 ? part1_0 : part2_0 ; use the smaller amount of parts
{
if part1_%A_Index% is digit
{
if part2_%A_Index% is digit ; both are numeric: compare numerically
{
part1_%A_Index% += 0, part2_%A_Index% += 0
if (part1_%A_Index% < part2_%A_Index%)
return -1
else if (part1_%A_Index% > part2_%A_Index%)
return +1
continue
}
}
; at least one is non-numeric: compare by characters
if (part1_%A_Index% < part2_%A_Index%)
return -1
else if (part1_%A_Index% > part2_%A_Index%)
return +1
}
; all compared parts were equal - the longer one wins
if (part1_0 < part2_0)
return -1
else if (part1_0 > part2_0)
return +1
}
else if (!%part%1 && %part%2) ; only version2 has prerelease -> version1 is higher
return (part == "pre") ? +1 : -1
else if (!%part%2 && %part%1) ; only version1 has prerelease -> it is smaller
return (part == "pre") ? -1 : +1
}
return 0
}
#include semver.ahk
data := ["01.0.0-alpha", "1.0.0-alpha.1", "1.0.0-beta.2", "1.0.0-beta.11", "1.0.0-rc.1", "1.0.0-rc.1+build.1", "1.0.0", "1.0.0+0.3.7", "1.3.7+build", "1.3.7+build.2.b8f12d7", "1.3.7+build.11.e0f985a"]
MsgBox separating...
for each, version in data
{
if (!semver_validate(version))
MsgBox Error: %version% is not valid (%A_Index%)
else if (!semver_parts(version, maj, min, pat, pre, bld))
MsgBox Error: %version% cannot be split (%A_Index%)
else
MsgBox Version: %version%`n`nMajor: %maj%`nMinor: %min%`nPatch: %pat%`nPrerelease: %pre%`nBuild: %bld%
}
MsgBox comparing...
failed := [], failed_count := 0
for index, version in data
{
if (A_Index == 1)
continue
if ((result := semver_compare(data[index - 1], version)) != -1)
failed[A_Index - 1] := result, failed_count++
}
msg := failed_count " of " (data.maxIndex() - 1) " tests failed (" Round(failed_count / (data.maxIndex() - 1) * 100, 2) "%)"
if (failed_count > 0)
{
msg .= "`n`nTests that failed:`n"
for test, result in failed
msg .= "`tTest " test " (items """ data[test] """ and """ data[test + 1] """) resulted in: " result "`n"
}
MsgBox %msg%
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment