From 4b82b111e7392e695b0e021efac2385c1b9850af Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Sun, 10 Jun 2018 21:50:24 -0400 Subject: improve semantic version validation --- src/StardewModdingAPI.Toolkit/SemanticVersion.cs | 27 +++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) (limited to 'src/StardewModdingAPI.Toolkit') diff --git a/src/StardewModdingAPI.Toolkit/SemanticVersion.cs b/src/StardewModdingAPI.Toolkit/SemanticVersion.cs index bd85f990..3008a4d6 100644 --- a/src/StardewModdingAPI.Toolkit/SemanticVersion.cs +++ b/src/StardewModdingAPI.Toolkit/SemanticVersion.cs @@ -10,8 +10,11 @@ namespace StardewModdingAPI.Toolkit /********* ** Properties *********/ + /// A regex pattern matching a valid prerelease tag. + internal const string TagPattern = @"(?>[a-z0-9]+[\-\.]?)+"; + /// A regex pattern matching a version within a larger string. - internal const string UnboundedVersionPattern = @"(?>(?0|[1-9]\d*))\.(?>(?0|[1-9]\d*))(?>(?:\.(?0|[1-9]\d*))?)(?:-(?(?>[a-z0-9]+[\-\.]?)+))?"; + internal const string UnboundedVersionPattern = @"(?>(?0|[1-9]\d*))\.(?>(?0|[1-9]\d*))(?>(?:\.(?0|[1-9]\d*))?)(?:-(?" + SemanticVersion.TagPattern + "))?"; /// A regular expression matching a semantic version string. /// @@ -54,6 +57,8 @@ namespace StardewModdingAPI.Toolkit this.Minor = minor; this.Patch = patch; this.Tag = this.GetNormalisedTag(tag); + + this.AssertValid(); } /// Construct an instance. @@ -67,6 +72,8 @@ namespace StardewModdingAPI.Toolkit this.Major = version.Major; this.Minor = version.Minor; this.Patch = version.Build; + + this.AssertValid(); } /// Construct an instance. @@ -87,6 +94,8 @@ namespace StardewModdingAPI.Toolkit this.Minor = match.Groups["minor"].Success ? int.Parse(match.Groups["minor"].Value) : 0; this.Patch = match.Groups["patch"].Success ? int.Parse(match.Groups["patch"].Value) : 0; this.Tag = match.Groups["prerelease"].Success ? this.GetNormalisedTag(match.Groups["prerelease"].Value) : null; + + this.AssertValid(); } /// Get an integer indicating whether this version precedes (less than 0), supercedes (more than 0), or is equivalent to (0) the specified version. @@ -235,5 +244,21 @@ namespace StardewModdingAPI.Toolkit // fallback (this should never happen) return string.Compare(this.ToString(), new SemanticVersion(otherMajor, otherMinor, otherPatch, otherTag).ToString(), StringComparison.InvariantCultureIgnoreCase); } + + /// Assert that the current version is valid. + private void AssertValid() + { + if (this.Major < 0 || this.Minor < 0 || this.Patch < 0) + throw new FormatException($"{this} isn't a valid semantic version. The major, minor, and patch numbers can't be negative."); + if (this.Major == 0 && this.Minor == 0 && this.Patch == 0) + throw new FormatException($"{this} isn't a valid semantic version. At least one of the major, minor, and patch numbers must be more than zero."); + if (this.Tag != null) + { + if (this.Tag.Trim() == "") + throw new FormatException($"{this} isn't a valid semantic version. The tag cannot be a blank string (but may be omitted)."); + if (!Regex.IsMatch(this.Tag, $"^{SemanticVersion.TagPattern}$")) + throw new FormatException($"{this} isn't a valid semantic version. The tag is invalid."); + } + } } } -- cgit