diff options
author | Jesse Plamondon-Willard <github@jplamondonw.com> | 2016-12-21 11:45:52 -0500 |
---|---|---|
committer | Jesse Plamondon-Willard <github@jplamondonw.com> | 2016-12-21 11:45:52 -0500 |
commit | ea65b2b7df78fd075caecac96937e9870e06e646 (patch) | |
tree | 77db25cfd1890e3d00c0bcf3347f64ce35b7f44b /src/StardewModdingAPI/SemanticVersion.cs | |
parent | 45ee74219ee931b5fef3b67c08adf79d55aa091d (diff) | |
download | SMAPI-ea65b2b7df78fd075caecac96937e9870e06e646.tar.gz SMAPI-ea65b2b7df78fd075caecac96937e9870e06e646.tar.bz2 SMAPI-ea65b2b7df78fd075caecac96937e9870e06e646.zip |
correct semantic version pre-release label precedence (#195)
Diffstat (limited to 'src/StardewModdingAPI/SemanticVersion.cs')
-rw-r--r-- | src/StardewModdingAPI/SemanticVersion.cs | 59 |
1 files changed, 45 insertions, 14 deletions
diff --git a/src/StardewModdingAPI/SemanticVersion.cs b/src/StardewModdingAPI/SemanticVersion.cs index b3d9ee4a..cf435aaa 100644 --- a/src/StardewModdingAPI/SemanticVersion.cs +++ b/src/StardewModdingAPI/SemanticVersion.cs @@ -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; - - // 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; - - // else compare by string + return this.PatchVersion.CompareTo(other.PatchVersion); + if (this.Build == other.Build) + return same; + + // stable supercedes pre-release + bool curIsStable = string.IsNullOrWhiteSpace(this.Build); + bool otherIsStable = string.IsNullOrWhiteSpace(other.Build); + if (curIsStable) + return curNewer; + if (otherIsStable) + return curOlder; + + // 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); } |