diff options
-rw-r--r-- | src/SMAPI.Installer/InteractiveInstaller.cs | 12 | ||||
-rw-r--r-- | src/SMAPI.Internal/SMAPI.Internal.projitems | 1 | ||||
-rw-r--r-- | src/SMAPI.ModBuildConfig/Framework/ModFileManager.cs | 6 | ||||
-rw-r--r-- | src/SMAPI.ModBuildConfig/StardewModdingAPI.ModBuildConfig.csproj | 6 | ||||
-rw-r--r-- | src/SMAPI.Web/Controllers/IndexController.cs | 8 | ||||
-rw-r--r-- | src/SMAPI.Web/Framework/LogParsing/LogParser.cs | 4 | ||||
-rw-r--r-- | src/SMAPI.Web/Framework/VersionConstraint.cs | 4 | ||||
-rw-r--r-- | src/SMAPI.Web/StardewModdingAPI.Web.csproj | 3 | ||||
-rw-r--r-- | src/SMAPI/SemanticVersion.cs | 16 | ||||
-rw-r--r-- | src/StardewModdingAPI.Toolkit/ISemanticVersion.cs | 46 | ||||
-rw-r--r-- | src/StardewModdingAPI.Toolkit/Properties/AssemblyInfo.cs | 1 | ||||
-rw-r--r-- | src/StardewModdingAPI.Toolkit/SemanticVersion.cs (renamed from src/SMAPI.Internal/SemanticVersionImpl.cs) | 176 |
12 files changed, 194 insertions, 89 deletions
diff --git a/src/SMAPI.Installer/InteractiveInstaller.cs b/src/SMAPI.Installer/InteractiveInstaller.cs index ace560e5..6e4cb95d 100644 --- a/src/SMAPI.Installer/InteractiveInstaller.cs +++ b/src/SMAPI.Installer/InteractiveInstaller.cs @@ -152,7 +152,7 @@ namespace StardewModdingApi.Installer ** Get platform & set window title ****/ Platform platform = EnvironmentUtility.DetectPlatform(); - Console.Title = $"SMAPI {new SemanticVersionImpl(this.GetType().Assembly.GetName().Version)} installer on {platform} {EnvironmentUtility.GetFriendlyPlatformName(platform)}"; + Console.Title = $"SMAPI {this.GetDisplayVersion(this.GetType().Assembly.GetName().Version)} installer on {platform} {EnvironmentUtility.GetFriendlyPlatformName(platform)}"; Console.WriteLine(); #if SMAPI_FOR_WINDOWS @@ -421,6 +421,16 @@ namespace StardewModdingApi.Installer /********* ** Private methods *********/ + /// <summary>Get the display text for an assembly version.</summary> + /// <param name="version">The assembly version.</param> + private string GetDisplayVersion(Version version) + { + string str = $"{version.Major}.{version.Minor}"; + if (version.Build != 0) + str += $".{version.Build}"; + return str; + } + /// <summary>Get the value of a key in the Windows registry.</summary> /// <param name="key">The full path of the registry key relative to HKLM.</param> /// <param name="name">The name of the value.</param> diff --git a/src/SMAPI.Internal/SMAPI.Internal.projitems b/src/SMAPI.Internal/SMAPI.Internal.projitems index dadae4b0..33b8cbfa 100644 --- a/src/SMAPI.Internal/SMAPI.Internal.projitems +++ b/src/SMAPI.Internal/SMAPI.Internal.projitems @@ -16,6 +16,5 @@ <Compile Include="$(MSBuildThisFileDirectory)Models\ModSeachModel.cs" /> <Compile Include="$(MSBuildThisFileDirectory)ConsoleWriting\MonitorColorScheme.cs" /> <Compile Include="$(MSBuildThisFileDirectory)Platform.cs" /> - <Compile Include="$(MSBuildThisFileDirectory)SemanticVersionImpl.cs" /> </ItemGroup> </Project>
\ No newline at end of file diff --git a/src/SMAPI.ModBuildConfig/Framework/ModFileManager.cs b/src/SMAPI.ModBuildConfig/Framework/ModFileManager.cs index 3fec8215..41e0201d 100644 --- a/src/SMAPI.ModBuildConfig/Framework/ModFileManager.cs +++ b/src/SMAPI.ModBuildConfig/Framework/ModFileManager.cs @@ -3,7 +3,7 @@ using System.Collections.Generic; using System.IO; using System.Linq; using System.Web.Script.Serialization; -using StardewModdingAPI.Internal; +using StardewModdingAPI.Toolkit; namespace StardewModdingAPI.ModBuildConfig.Framework { @@ -132,9 +132,9 @@ namespace StardewModdingAPI.ModBuildConfig.Framework int minor = versionFields.ContainsKey("MinorVersion") ? (int)versionFields["MinorVersion"] : 0; int patch = versionFields.ContainsKey("PatchVersion") ? (int)versionFields["PatchVersion"] : 0; string tag = versionFields.ContainsKey("Build") ? (string)versionFields["Build"] : null; - return new SemanticVersionImpl(major, minor, patch, tag).ToString(); + return new SemanticVersion(major, minor, patch, tag).ToString(); } - return new SemanticVersionImpl(versionObj.ToString()).ToString(); // SMAPI 2.0+ + return new SemanticVersion(versionObj.ToString()).ToString(); // SMAPI 2.0+ } diff --git a/src/SMAPI.ModBuildConfig/StardewModdingAPI.ModBuildConfig.csproj b/src/SMAPI.ModBuildConfig/StardewModdingAPI.ModBuildConfig.csproj index e0ea876f..6a52daac 100644 --- a/src/SMAPI.ModBuildConfig/StardewModdingAPI.ModBuildConfig.csproj +++ b/src/SMAPI.ModBuildConfig/StardewModdingAPI.ModBuildConfig.csproj @@ -55,6 +55,12 @@ <ItemGroup> <Content Include="assets\nuget-icon.png" /> </ItemGroup> + <ItemGroup> + <ProjectReference Include="..\StardewModdingAPI.Toolkit\StardewModdingAPI.Toolkit.csproj"> + <Project>{ea5cfd2e-9453-4d29-b80f-8e0ea23f4ac6}</Project> + <Name>StardewModdingAPI.Toolkit</Name> + </ProjectReference> + </ItemGroup> <Import Project="..\SMAPI.Internal\SMAPI.Internal.projitems" Label="Shared" /> <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> <Import Project="..\..\build\common.targets" /> diff --git a/src/SMAPI.Web/Controllers/IndexController.cs b/src/SMAPI.Web/Controllers/IndexController.cs index 08b7363a..0cc3c37a 100644 --- a/src/SMAPI.Web/Controllers/IndexController.cs +++ b/src/SMAPI.Web/Controllers/IndexController.cs @@ -5,7 +5,7 @@ using System.Text.RegularExpressions; using System.Threading.Tasks; using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Caching.Memory; -using StardewModdingAPI.Internal; +using StardewModdingAPI.Toolkit; using StardewModdingAPI.Web.Framework.Clients.GitHub; using StardewModdingAPI.Web.ViewModels; @@ -105,7 +105,7 @@ namespace StardewModdingAPI.Web.Controllers foreach (GitAsset asset in release.Assets) { Match match = Regex.Match(asset.FileName, @"SMAPI-(?<version>[\d\.]+(?:-.+)?)-installer(?<forDevs>-for-developers)?.zip"); - if (!match.Success || !SemanticVersionImpl.TryParse(match.Groups["version"].Value, out SemanticVersionImpl version)) + if (!match.Success || !SemanticVersion.TryParse(match.Groups["version"].Value, out ISemanticVersion version)) continue; bool isBeta = version.Tag != null; bool isForDevs = match.Groups["forDevs"].Success; @@ -127,7 +127,7 @@ namespace StardewModdingAPI.Web.Controllers public GitAsset Asset { get; } /// <summary>The SMAPI version.</summary> - public SemanticVersionImpl Version { get; } + public ISemanticVersion Version { get; } /// <summary>Whether this is a beta download.</summary> public bool IsBeta { get; } @@ -145,7 +145,7 @@ namespace StardewModdingAPI.Web.Controllers /// <param name="version">The SMAPI version.</param> /// <param name="isBeta">Whether this is a beta download.</param> /// <param name="isForDevs">Whether this is a 'for developers' download.</param> - public ReleaseVersion(GitRelease release, GitAsset asset, SemanticVersionImpl version, bool isBeta, bool isForDevs) + public ReleaseVersion(GitRelease release, GitAsset asset, ISemanticVersion version, bool isBeta, bool isForDevs) { this.Release = release; this.Asset = asset; diff --git a/src/SMAPI.Web/Framework/LogParsing/LogParser.cs b/src/SMAPI.Web/Framework/LogParsing/LogParser.cs index 163176fd..c50e643a 100644 --- a/src/SMAPI.Web/Framework/LogParsing/LogParser.cs +++ b/src/SMAPI.Web/Framework/LogParsing/LogParser.cs @@ -3,7 +3,7 @@ using System.Collections.Generic; using System.IO; using System.Linq; using System.Text.RegularExpressions; -using StardewModdingAPI.Internal; +using StardewModdingAPI.Toolkit; using StardewModdingAPI.Web.Framework.LogParsing.Models; namespace StardewModdingAPI.Web.Framework.LogParsing @@ -31,7 +31,7 @@ namespace StardewModdingAPI.Web.Framework.LogParsing /// <summary>A regex pattern matching an entry in SMAPI's mod list.</summary> /// <remarks>The author name and description are optional.</remarks> - private readonly Regex ModListEntryPattern = new Regex(@"^ (?<name>.+?) (?<version>" + SemanticVersionImpl.UnboundedVersionPattern + @")(?: by (?<author>[^\|]+))?(?: \| (?<description>.+))?$", RegexOptions.Compiled | RegexOptions.IgnoreCase); + private readonly Regex ModListEntryPattern = new Regex(@"^ (?<name>.+?) (?<version>" + SemanticVersion.UnboundedVersionPattern + @")(?: by (?<author>[^\|]+))?(?: \| (?<description>.+))?$", RegexOptions.Compiled | RegexOptions.IgnoreCase); /// <summary>A regex pattern matching the start of SMAPI's content pack list.</summary> private readonly Regex ContentPackListStartPattern = new Regex(@"^Loaded \d+ content packs:$", RegexOptions.Compiled | RegexOptions.IgnoreCase); diff --git a/src/SMAPI.Web/Framework/VersionConstraint.cs b/src/SMAPI.Web/Framework/VersionConstraint.cs index 1502f5d8..2d6ec603 100644 --- a/src/SMAPI.Web/Framework/VersionConstraint.cs +++ b/src/SMAPI.Web/Framework/VersionConstraint.cs @@ -1,5 +1,5 @@ using Microsoft.AspNetCore.Routing.Constraints; -using StardewModdingAPI.Internal; +using StardewModdingAPI.Toolkit; namespace StardewModdingAPI.Web.Framework { @@ -11,6 +11,6 @@ namespace StardewModdingAPI.Web.Framework *********/ /// <summary>Construct an instance.</summary> public VersionConstraint() - : base(SemanticVersionImpl.Regex) { } + : base(SemanticVersion.Regex) { } } } diff --git a/src/SMAPI.Web/StardewModdingAPI.Web.csproj b/src/SMAPI.Web/StardewModdingAPI.Web.csproj index e4678269..202a8376 100644 --- a/src/SMAPI.Web/StardewModdingAPI.Web.csproj +++ b/src/SMAPI.Web/StardewModdingAPI.Web.csproj @@ -23,5 +23,8 @@ <DotNetCliToolReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Tools" Version="1.0.1" /> </ItemGroup> <Import Project="..\SMAPI.Internal\SMAPI.Internal.projitems" Label="Shared" /> + <ItemGroup> + <ProjectReference Include="..\StardewModdingAPI.Toolkit\StardewModdingAPI.Toolkit.csproj" /> + </ItemGroup> </Project> diff --git a/src/SMAPI/SemanticVersion.cs b/src/SMAPI/SemanticVersion.cs index 9db1cf14..3ee3ccf3 100644 --- a/src/SMAPI/SemanticVersion.cs +++ b/src/SMAPI/SemanticVersion.cs @@ -1,6 +1,5 @@ using System; using Newtonsoft.Json; -using StardewModdingAPI.Internal; namespace StardewModdingAPI { @@ -11,7 +10,7 @@ namespace StardewModdingAPI ** Properties *********/ /// <summary>The underlying semantic version implementation.</summary> - private readonly SemanticVersionImpl Version; + private readonly Toolkit.ISemanticVersion Version; /********* @@ -40,20 +39,20 @@ namespace StardewModdingAPI /// <param name="build">An optional build tag.</param> [JsonConstructor] public SemanticVersion(int majorVersion, int minorVersion, int patchVersion, string build = null) - : this(new SemanticVersionImpl(majorVersion, minorVersion, patchVersion, build)) { } + : this(new Toolkit.SemanticVersion(majorVersion, minorVersion, patchVersion, build)) { } /// <summary>Construct an instance.</summary> /// <param name="version">The semantic version string.</param> /// <exception cref="ArgumentNullException">The <paramref name="version"/> is null.</exception> /// <exception cref="FormatException">The <paramref name="version"/> is not a valid semantic version.</exception> public SemanticVersion(string version) - : this(new SemanticVersionImpl(version)) { } + : this(new Toolkit.SemanticVersion(version)) { } /// <summary>Construct an instance.</summary> /// <param name="version">The assembly version.</param> /// <exception cref="ArgumentNullException">The <paramref name="version"/> is null.</exception> public SemanticVersion(Version version) - : this(new SemanticVersionImpl(version)) { } + : this(new Toolkit.SemanticVersion(version)) { } /// <summary>Whether this is a pre-release version.</summary> public bool IsPrerelease() @@ -67,7 +66,8 @@ namespace StardewModdingAPI /// <remarks>The implementation is defined by Semantic Version 2.0 (http://semver.org/).</remarks> public int CompareTo(ISemanticVersion other) { - return this.Version.CompareTo(other.MajorVersion, other.MinorVersion, other.PatchVersion, other.Build); + Toolkit.ISemanticVersion toolkitOther = new Toolkit.SemanticVersion(other.MajorVersion, other.MinorVersion, other.PatchVersion, other.Build); + return this.Version.CompareTo(toolkitOther); } /// <summary>Get whether this version is older than the specified version.</summary> @@ -137,7 +137,7 @@ namespace StardewModdingAPI /// <returns>Returns whether parsing the version succeeded.</returns> internal static bool TryParse(string version, out ISemanticVersion parsed) { - if (SemanticVersionImpl.TryParse(version, out SemanticVersionImpl versionImpl)) + if (Toolkit.SemanticVersion.TryParse(version, out Toolkit.ISemanticVersion versionImpl)) { parsed = new SemanticVersion(versionImpl); return true; @@ -153,7 +153,7 @@ namespace StardewModdingAPI *********/ /// <summary>Construct an instance.</summary> /// <param name="version">The underlying semantic version implementation.</param> - private SemanticVersion(SemanticVersionImpl version) + private SemanticVersion(Toolkit.ISemanticVersion version) { this.Version = version; } diff --git a/src/StardewModdingAPI.Toolkit/ISemanticVersion.cs b/src/StardewModdingAPI.Toolkit/ISemanticVersion.cs new file mode 100644 index 00000000..ca62d393 --- /dev/null +++ b/src/StardewModdingAPI.Toolkit/ISemanticVersion.cs @@ -0,0 +1,46 @@ +using System; + +namespace StardewModdingAPI.Toolkit +{ + /// <summary>A semantic version with an optional release tag.</summary> + public interface ISemanticVersion : IComparable<ISemanticVersion>, IEquatable<ISemanticVersion> + { + /********* + ** Accessors + *********/ + /// <summary>The major version incremented for major API changes.</summary> + int Major { get; } + + /// <summary>The minor version incremented for backwards-compatible changes.</summary> + int Minor { get; } + + /// <summary>The patch version for backwards-compatible bug fixes.</summary> + int Patch { get; } + + /// <summary>An optional prerelease tag.</summary> + string Tag { get; } + + + /********* + ** Accessors + *********/ + /// <summary>Whether this is a pre-release version.</summary> + bool IsPrerelease(); + + /// <summary>Get whether this version is older than the specified version.</summary> + /// <param name="other">The version to compare with this instance.</param> + bool IsOlderThan(ISemanticVersion other); + + /// <summary>Get whether this version is newer than the specified version.</summary> + /// <param name="other">The version to compare with this instance.</param> + bool IsNewerThan(ISemanticVersion other); + + /// <summary>Get whether this version is between two specified versions (inclusively).</summary> + /// <param name="min">The minimum version.</param> + /// <param name="max">The maximum version.</param> + bool IsBetween(ISemanticVersion min, ISemanticVersion max); + + /// <summary>Get a string representation of the version.</summary> + string ToString(); + } +} diff --git a/src/StardewModdingAPI.Toolkit/Properties/AssemblyInfo.cs b/src/StardewModdingAPI.Toolkit/Properties/AssemblyInfo.cs index 20118fce..9b55dac6 100644 --- a/src/StardewModdingAPI.Toolkit/Properties/AssemblyInfo.cs +++ b/src/StardewModdingAPI.Toolkit/Properties/AssemblyInfo.cs @@ -4,3 +4,4 @@ using System.Runtime.CompilerServices; [assembly: AssemblyTitle("SMAPI.Toolkit")] [assembly: AssemblyDescription("")] [assembly: InternalsVisibleTo("StardewModdingAPI")] +[assembly: InternalsVisibleTo("StardewModdingAPI.Web")] diff --git a/src/SMAPI.Internal/SemanticVersionImpl.cs b/src/StardewModdingAPI.Toolkit/SemanticVersion.cs index 7ae34f07..bd85f990 100644 --- a/src/SMAPI.Internal/SemanticVersionImpl.cs +++ b/src/StardewModdingAPI.Toolkit/SemanticVersion.cs @@ -1,13 +1,30 @@ using System; using System.Text.RegularExpressions; -namespace StardewModdingAPI.Internal +namespace StardewModdingAPI.Toolkit { - /// <summary>A low-level implementation of a semantic version with an optional release tag.</summary> + /// <summary>A semantic version with an optional release tag.</summary> /// <remarks>The implementation is defined by Semantic Version 2.0 (http://semver.org/).</remarks> - internal class SemanticVersionImpl : IComparable<SemanticVersionImpl> + public class SemanticVersion : ISemanticVersion { /********* + ** Properties + *********/ + /// <summary>A regex pattern matching a version within a larger string.</summary> + internal const string UnboundedVersionPattern = @"(?>(?<major>0|[1-9]\d*))\.(?>(?<minor>0|[1-9]\d*))(?>(?:\.(?<patch>0|[1-9]\d*))?)(?:-(?<prerelease>(?>[a-z0-9]+[\-\.]?)+))?"; + + /// <summary>A regular expression matching a semantic version string.</summary> + /// <remarks> + /// This pattern is derived from the BNF documentation in the <a href="https://github.com/mojombo/semver">semver repo</a>, + /// with three important deviations intended to support Stardew Valley mod conventions: + /// - allows short-form "x.y" versions; + /// - allows hyphens in prerelease tags as synonyms for dots (like "-unofficial-update.3"); + /// - doesn't allow '+build' suffixes. + /// </remarks> + internal static readonly Regex Regex = new Regex($@"^{SemanticVersion.UnboundedVersionPattern}$", RegexOptions.CultureInvariant | RegexOptions.IgnoreCase | RegexOptions.Compiled | RegexOptions.ExplicitCapture); + + + /********* ** Accessors *********/ /// <summary>The major version incremented for major API changes.</summary> @@ -22,18 +39,6 @@ namespace StardewModdingAPI.Internal /// <summary>An optional prerelease tag.</summary> public string Tag { get; } - /// <summary>A regex pattern matching a version within a larger string.</summary> - internal const string UnboundedVersionPattern = @"(?>(?<major>0|[1-9]\d*))\.(?>(?<minor>0|[1-9]\d*))(?>(?:\.(?<patch>0|[1-9]\d*))?)(?:-(?<prerelease>(?>[a-z0-9]+[\-\.]?)+))?"; - - /// <summary>A regular expression matching a semantic version string.</summary> - /// <remarks> - /// This pattern is derived from the BNF documentation in the <a href="https://github.com/mojombo/semver">semver repo</a>, - /// with three important deviations intended to support Stardew Valley mod conventions: - /// - allows short-form "x.y" versions; - /// - allows hyphens in prerelease tags as synonyms for dots (like "-unofficial-update.3"); - /// - doesn't allow '+build' suffixes. - /// </remarks> - internal static readonly Regex Regex = new Regex($@"^{SemanticVersionImpl.UnboundedVersionPattern}$", RegexOptions.CultureInvariant | RegexOptions.IgnoreCase | RegexOptions.Compiled | RegexOptions.ExplicitCapture); /********* ** Public methods @@ -41,9 +46,9 @@ namespace StardewModdingAPI.Internal /// <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="patch">The patch version for backwards-compatible fixes.</param> /// <param name="tag">An optional prerelease tag.</param> - public SemanticVersionImpl(int major, int minor, int patch, string tag = null) + public SemanticVersion(int major, int minor, int patch, string tag = null) { this.Major = major; this.Minor = minor; @@ -54,7 +59,7 @@ namespace StardewModdingAPI.Internal /// <summary>Construct an instance.</summary> /// <param name="version">The assembly version.</param> /// <exception cref="ArgumentNullException">The <paramref name="version"/> is null.</exception> - public SemanticVersionImpl(Version version) + public SemanticVersion(Version version) { if (version == null) throw new ArgumentNullException(nameof(version), "The input version can't be null."); @@ -68,12 +73,12 @@ namespace StardewModdingAPI.Internal /// <param name="version">The semantic version string.</param> /// <exception cref="ArgumentNullException">The <paramref name="version"/> is null.</exception> /// <exception cref="FormatException">The <paramref name="version"/> is not a valid semantic version.</exception> - public SemanticVersionImpl(string version) + public SemanticVersion(string version) { // parse if (version == null) throw new ArgumentNullException(nameof(version), "The input version string can't be null."); - var match = SemanticVersionImpl.Regex.Match(version.Trim()); + var match = SemanticVersion.Regex.Match(version.Trim()); if (!match.Success) throw new FormatException($"The input '{version}' isn't a valid semantic version."); @@ -87,20 +92,100 @@ namespace StardewModdingAPI.Internal /// <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> /// <exception cref="ArgumentNullException">The <paramref name="other"/> value is null.</exception> - public int CompareTo(SemanticVersionImpl other) + public int CompareTo(ISemanticVersion other) { if (other == null) throw new ArgumentNullException(nameof(other)); return this.CompareTo(other.Major, other.Minor, other.Patch, other.Tag); } + /// <summary>Indicates whether the current object is equal to another object of the same type.</summary> + /// <returns>true if the current object is equal to the <paramref name="other" /> parameter; otherwise, false.</returns> + /// <param name="other">An object to compare with this object.</param> + public bool Equals(ISemanticVersion other) + { + return other != null && this.CompareTo(other) == 0; + } + + /// <summary>Whether this is a pre-release version.</summary> + public bool IsPrerelease() + { + return !string.IsNullOrWhiteSpace(this.Tag); + } + + /// <summary>Get whether this version is older than the specified version.</summary> + /// <param name="other">The version to compare with this instance.</param> + public bool IsOlderThan(ISemanticVersion other) + { + return this.CompareTo(other) < 0; + } + + /// <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(ISemanticVersion other) + { + return this.CompareTo(other) > 0; + } + + /// <summary>Get whether this version is between two specified versions (inclusively).</summary> + /// <param name="min">The minimum version.</param> + /// <param name="max">The maximum version.</param> + public bool IsBetween(ISemanticVersion min, ISemanticVersion max) + { + return this.CompareTo(min) >= 0 && this.CompareTo(max) <= 0; + } + + /// <summary>Get a string representation of the version.</summary> + public override string ToString() + { + // version + string result = this.Patch != 0 + ? $"{this.Major}.{this.Minor}.{this.Patch}" + : $"{this.Major}.{this.Minor}"; + + // tag + string tag = this.Tag; + if (tag != null) + result += $"-{tag}"; + return result; + } + + /// <summary>Parse a version string without throwing an exception if it fails.</summary> + /// <param name="version">The version string.</param> + /// <param name="parsed">The parsed representation.</param> + /// <returns>Returns whether parsing the version succeeded.</returns> + public static bool TryParse(string version, out ISemanticVersion parsed) + { + try + { + parsed = new SemanticVersion(version); + return true; + } + catch + { + parsed = null; + return false; + } + } + + + /********* + ** Private methods + *********/ + /// <summary>Get a normalised build tag.</summary> + /// <param name="tag">The tag to normalise.</param> + private string GetNormalisedTag(string tag) + { + tag = tag?.Trim(); + return !string.IsNullOrWhiteSpace(tag) ? tag : null; + } /// <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="otherMajor">The major version to compare with this instance.</param> /// <param name="otherMinor">The minor version to compare with this instance.</param> /// <param name="otherPatch">The patch version to compare with this instance.</param> /// <param name="otherTag">The prerelease tag to compare with this instance.</param> - public int CompareTo(int otherMajor, int otherMinor, int otherPatch, string otherTag) + private int CompareTo(int otherMajor, int otherMinor, int otherPatch, string otherTag) { const int same = 0; const int curNewer = 1; @@ -148,52 +233,7 @@ namespace StardewModdingAPI.Internal } // fallback (this should never happen) - return string.Compare(this.ToString(), new SemanticVersionImpl(otherMajor, otherMinor, otherPatch, otherTag).ToString(), StringComparison.InvariantCultureIgnoreCase); - } - - /// <summary>Get a string representation of the version.</summary> - public override string ToString() - { - // version - string result = this.Patch != 0 - ? $"{this.Major}.{this.Minor}.{this.Patch}" - : $"{this.Major}.{this.Minor}"; - - // tag - string tag = this.Tag; - if (tag != null) - result += $"-{tag}"; - return result; - } - - /// <summary>Parse a version string without throwing an exception if it fails.</summary> - /// <param name="version">The version string.</param> - /// <param name="parsed">The parsed representation.</param> - /// <returns>Returns whether parsing the version succeeded.</returns> - internal static bool TryParse(string version, out SemanticVersionImpl parsed) - { - try - { - parsed = new SemanticVersionImpl(version); - return true; - } - catch - { - parsed = null; - return false; - } - } - - - /********* - ** Private methods - *********/ - /// <summary>Get a normalised build tag.</summary> - /// <param name="tag">The tag to normalise.</param> - private string GetNormalisedTag(string tag) - { - tag = tag?.Trim(); - return !string.IsNullOrWhiteSpace(tag) ? tag : null; + return string.Compare(this.ToString(), new SemanticVersion(otherMajor, otherMinor, otherPatch, otherTag).ToString(), StringComparison.InvariantCultureIgnoreCase); } } } |