correct semantic version pre-release label precedence (#195)

This commit is contained in:
Jesse Plamondon-Willard 2016-12-21 11:45:52 -05:00
parent 45ee74219e
commit ea65b2b7df
1 changed files with 43 additions and 12 deletions

View File

@ -48,25 +48,56 @@ namespace StardewModdingAPI
/// <summary>Get an integer indicating whether this version precedes (less than 0), supercedes (more than 0), or is equivalent to (0) the specified version.</summary>
/// <param name="other">The version to compare with this instance.</param>
/// <remarks>The implementation is defined by Semantic Version 2.0 (http://semver.org/).</remarks>
public int CompareTo(ISemanticVersion other)
{
// compare version numbers
const int same = 0;
const int curNewer = 1;
const int curOlder = -1;
// compare stable versions
if (this.MajorVersion != other.MajorVersion)
return this.MajorVersion - other.MajorVersion;
return this.MajorVersion.CompareTo(other.MajorVersion);
if (this.MinorVersion != other.MinorVersion)
return this.MinorVersion - other.MinorVersion;
return this.MinorVersion.CompareTo(other.MinorVersion);
if (this.PatchVersion != other.PatchVersion)
return this.PatchVersion - other.PatchVersion;
return this.PatchVersion.CompareTo(other.PatchVersion);
if (this.Build == other.Build)
return same;
// stable version (without tag) supercedes prerelease (with tag)
bool curHasTag = !string.IsNullOrWhiteSpace(this.Build);
bool otherHasTag = !string.IsNullOrWhiteSpace(other.Build);
if (!curHasTag && otherHasTag)
return 1;
if (curHasTag && !otherHasTag)
return -1;
// stable supercedes pre-release
bool curIsStable = string.IsNullOrWhiteSpace(this.Build);
bool otherIsStable = string.IsNullOrWhiteSpace(other.Build);
if (curIsStable)
return curNewer;
if (otherIsStable)
return curOlder;
// else compare by string
// compare two pre-release tag values
string[] curParts = this.Build.Split('.');
string[] otherParts = other.Build.Split('.');
for (int i = 0; i < curParts.Length; i++)
{
// longer prerelease tag supercedes if otherwise equal
if (otherParts.Length <= i)
return curNewer;
// compare if different
if (curParts[i] != otherParts[i])
{
// compare numerically if possible
{
int curNum, otherNum;
if (int.TryParse(curParts[i], out curNum) && int.TryParse(otherParts[i], out otherNum))
return curNum.CompareTo(otherNum);
}
// else compare lexically
return string.Compare(curParts[i], otherParts[i], StringComparison.OrdinalIgnoreCase);
}
}
// fallback (this should never happen)
return string.Compare(this.ToString(), other.ToString(), StringComparison.InvariantCultureIgnoreCase);
}