summaryrefslogtreecommitdiff
path: root/src/StardewModdingAPI/Version.cs
diff options
context:
space:
mode:
Diffstat (limited to 'src/StardewModdingAPI/Version.cs')
-rw-r--r--src/StardewModdingAPI/Version.cs116
1 files changed, 50 insertions, 66 deletions
diff --git a/src/StardewModdingAPI/Version.cs b/src/StardewModdingAPI/Version.cs
index bdecc8e0..87cd4f3d 100644
--- a/src/StardewModdingAPI/Version.cs
+++ b/src/StardewModdingAPI/Version.cs
@@ -1,22 +1,14 @@
using System;
-using System.Text.RegularExpressions;
using Newtonsoft.Json;
using StardewModdingAPI.Framework;
namespace StardewModdingAPI
{
/// <summary>A semantic version with an optional release tag.</summary>
- public struct Version : IComparable<Version>
+ [Obsolete("Use " + nameof(SemanticVersion) + " or " + nameof(Manifest) + "." + nameof(Manifest.Version) + " instead")]
+ public struct Version : ISemanticVersion
{
/*********
- ** Properties
- *********/
- /// <summary>A regular expression matching a semantic version string.</summary>
- /// <remarks>Derived from https://github.com/maxhauser/semver.</remarks>
- private static readonly Regex Regex = new Regex(@"^(?<major>\d+)(\.(?<minor>\d+))?(\.(?<patch>\d+))?(?<build>.*)$", RegexOptions.CultureInvariant | RegexOptions.ExplicitCapture);
-
-
- /*********
** Accessors
*********/
/// <summary>The major version incremented for major API changes.</summary>
@@ -39,7 +31,7 @@ namespace StardewModdingAPI
get
{
Program.DeprecationManager.Warn($"{nameof(Version)}.{nameof(Version.VersionString)}", "1.0", DeprecationLevel.Notice);
- return this.ToString();
+ return this.GetSemanticVersion().ToString();
}
}
@@ -53,85 +45,77 @@ namespace StardewModdingAPI
/// <param name="patch">The patch version for backwards-compatible bug fixes.</param>
/// <param name="build">An optional build tag.</param>
public Version(int major, int minor, int patch, string build)
+ : this(major, minor, patch, build, suppressDeprecationWarning: false)
+ { }
+
+ /// <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>
+ public int CompareTo(Version other)
{
- this.MajorVersion = major;
- this.MinorVersion = minor;
- this.PatchVersion = patch;
- this.Build = build;
+ return this.GetSemanticVersion().CompareTo(other);
}
- /// <summary>Construct an instance.</summary>
- /// <param name="version">The semantic version string.</param>
- internal Version(string version)
+ /// <summary>Get whether this version is newer than the specified version.</summary>
+ /// <param name="other">The version to compare with this instance.</param>
+ [Obsolete("Use " + nameof(ISemanticVersion) + "." + nameof(ISemanticVersion.IsNewerThan) + " instead")]
+ public bool IsNewerThan(Version other)
{
- var match = Version.Regex.Match(version);
- if (!match.Success)
- throw new FormatException($"The input '{version}' is not a semantic version.");
-
- this.MajorVersion = int.Parse(match.Groups["major"].Value);
- this.MinorVersion = match.Groups["minor"].Success ? int.Parse(match.Groups["minor"].Value) : 0;
- this.PatchVersion = match.Groups["patch"].Success ? int.Parse(match.Groups["patch"].Value) : 0;
- this.Build = (match.Groups["build"].Success ? match.Groups["build"].Value : "").Trim(' ', '-', '.');
+ return this.GetSemanticVersion().IsNewerThan(other);
}
- /// <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>
+ /// <summary>Compares the current instance with another object of the same type and returns an integer that indicates whether the current instance precedes, follows, or occurs in the same position in the sort order as the other object. </summary>
+ /// <returns>A value that indicates the relative order of the objects being compared. The return value has these meanings: Value Meaning Less than zero This instance precedes <paramref name="other" /> in the sort order. Zero This instance occurs in the same position in the sort order as <paramref name="other" />. Greater than zero This instance follows <paramref name="other" /> in the sort order. </returns>
+ /// <param name="other">An object to compare with this instance. </param>
+ int IComparable<ISemanticVersion>.CompareTo(ISemanticVersion other)
+ {
+ return this.GetSemanticVersion().CompareTo(other);
+ }
+
+ /// <summary>Get whether this version is older than the specified version.</summary>
/// <param name="other">The version to compare with this instance.</param>
- public int CompareTo(Version other)
+ bool ISemanticVersion.IsOlderThan(ISemanticVersion other)
{
- // compare version numbers
- if (this.MajorVersion != other.MajorVersion)
- return this.MajorVersion - other.MajorVersion;
- if (this.MinorVersion != other.MinorVersion)
- return this.MinorVersion - 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 string.Compare(this.ToString(), other.ToString(), StringComparison.InvariantCultureIgnoreCase);
+ return this.GetSemanticVersion().IsOlderThan(other);
}
/// <summary>Get whether this version is newer than the specified version.</summary>
/// <param name="other">The version to compare with this instance.</param>
- public bool IsNewerThan(Version other)
+ bool ISemanticVersion.IsNewerThan(ISemanticVersion other)
{
- return this.CompareTo(other) > 0;
+ return this.GetSemanticVersion().IsNewerThan(other);
}
/// <summary>Get a string representation of the version.</summary>
public override string ToString()
{
- // version
- string result = this.PatchVersion != 0
- ? $"{this.MajorVersion}.{this.MinorVersion}.{this.PatchVersion}"
- : $"{this.MajorVersion}.{this.MinorVersion}";
-
- // tag
- string tag = this.GetNormalisedTag(this.Build);
- if (tag != null)
- result += $"-{tag}";
- return result;
+ return this.GetSemanticVersion().ToString();
}
-
/*********
** Private methods
*********/
- /// <summary>Get a normalised build tag.</summary>
- /// <param name="tag">The tag to normalise.</param>
- private string GetNormalisedTag(string tag)
+ /// <summary>Construct an instance.</summary>
+ /// <param name="major">The major version incremented for major API changes.</param>
+ /// <param name="minor">The minor version incremented for backwards-compatible changes.</param>
+ /// <param name="patch">The patch version for backwards-compatible bug fixes.</param>
+ /// <param name="build">An optional build tag.</param>
+ /// <param name="suppressDeprecationWarning">Whether to suppress the deprecation warning.</param>
+ internal Version(int major, int minor, int patch, string build, bool suppressDeprecationWarning)
+ {
+ if (!suppressDeprecationWarning)
+ Program.DeprecationManager.Warn($"{nameof(Version)}", "1.5", DeprecationLevel.Notice);
+
+ this.MajorVersion = major;
+ this.MinorVersion = minor;
+ this.PatchVersion = patch;
+ this.Build = build;
+ }
+
+ /// <summary>Get the equivalent semantic version.</summary>
+ /// <remarks>This is a hack so the struct can wrap <see cref="SemanticVersion"/> without a mutable backing field, which would cause a <see cref="StackOverflowException"/> due to recreating the struct value on each change.</remarks>
+ private SemanticVersion GetSemanticVersion()
{
- tag = tag?.Trim().Trim('-', '.');
- if (string.IsNullOrWhiteSpace(tag) || tag == "0")
- return null;
- return tag;
+ return new SemanticVersion(this.MajorVersion, this.MinorVersion, this.PatchVersion, this.Build);
}
}
}