Skip to content

Commit

Permalink
Merge pull request #9 from augustoproiete/minver-parse-try-parse
Browse files Browse the repository at this point in the history
Add Parse/TryParse methods to MinVerVersion
  • Loading branch information
augustoproiete authored Nov 27, 2020
2 parents 4145340 + ec3febf commit 174bf20
Show file tree
Hide file tree
Showing 2 changed files with 142 additions and 33 deletions.
132 changes: 101 additions & 31 deletions src/Cake.MinVer/MinVerVersion.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,60 +13,51 @@ public class MinVerVersion : IComparable<MinVerVersion>
/// <summary>
/// Initializes a new instance of the <see cref="MinVerVersion" /> class.
/// </summary>
/// <param name="version">The version string returned by MinVer</param>
public MinVerVersion(string version)
/// <param name="versionString">The version string returned by MinVer</param>
public MinVerVersion(string versionString)
{
if (string.IsNullOrWhiteSpace(version))
if (string.IsNullOrWhiteSpace(versionString))
{
throw new ArgumentException("Value cannot be null or whitespace.", nameof(version));
throw new ArgumentException("Value cannot be null or whitespace.", nameof(versionString));
}

var metaSplit = version.Split(new[] { '+' }, count: 2);
var preSplit = metaSplit[0].Split(new[] { '-' }, count: 2);
var rtmSplit = preSplit[0].Split('.');

var major = rtmSplit[0];
var minor = rtmSplit[1];
var patch = rtmSplit[2];
var preRelease = preSplit.ElementAtOrDefault(1);
var buildMetadata = metaSplit.ElementAtOrDefault(1);

Major = int.Parse(major, CultureInfo.InvariantCulture);
Minor = int.Parse(minor, CultureInfo.InvariantCulture);
Patch = int.Parse(patch, CultureInfo.InvariantCulture);

PreRelease = preRelease;
BuildMetadata = buildMetadata;
if (!TryParseAndFill(versionString, this))
{
throw new FormatException($"The string '{versionString}' was not recognized as a valid MinVer version");
}
}

AssemblyVersion = $"{Major}.0.0.0";
FileVersion = $"{Major}.{Minor}.{Patch}.0";
Version = version;
/// <summary>
/// Initializes a new instance of the <see cref="MinVerVersion" /> class.
/// </summary>
protected internal MinVerVersion()
{
}

/// <summary>
/// The original, non-normalized version string
/// </summary>
public string Version { get; }
public string Version { get; private set; }

/// <summary>
/// The Major version number
/// </summary>
public int Major { get; }
public int Major { get; private set; }

/// <summary>
/// The Minor version number
/// </summary>
public int Minor { get; }
public int Minor { get; private set; }

/// <summary>
/// The Patch version number
/// </summary>
public int Patch { get; }
public int Patch { get; private set; }

/// <summary>
/// The Pre-release extension
/// </summary>
public string PreRelease { get; }
public string PreRelease { get; private set; }

/// <summary>
/// Returns <see langword="true"/> when <see cref="PreRelease" /> is not null or empty
Expand All @@ -77,17 +68,17 @@ public MinVerVersion(string version)
/// <summary>
/// The Build metadata extension
/// </summary>
public string BuildMetadata { get; }
public string BuildMetadata { get; private set; }

/// <summary>
/// <see cref="Major" />.0.0.0
/// </summary>
public string AssemblyVersion { get; }
public string AssemblyVersion { get; private set; }

/// <summary>
/// <see cref="Major" />.<see cref="Minor" />.<see cref="Patch" />.0
/// </summary>
public string FileVersion { get; }
public string FileVersion { get; private set; }

/// <summary>
/// The original, non-normalized version string. Same as <see cref="Version" />
Expand All @@ -99,10 +90,89 @@ public MinVerVersion(string version)
/// </summary>
public string PackageVersion => Version;

/// <summary>
/// Converts the specified string representation of MinVer-compatible version to its <see cref="MinVerVersion" /> equivalent.
/// </summary>
/// <param name="versionString">A string containing a string version to convert.</param>
/// <returns>An object that is equivalent to the version contained in <paramref name="versionString">versionString</paramref>.</returns>
/// <exception cref="T:System.ArgumentNullException"><paramref name="versionString">versionString</paramref> is null or empty.</exception>
/// <exception cref="T:System.FormatException"><paramref name="versionString">versionString</paramref> does not contain a valid string representation of MinVer-compatible version.</exception>
public static MinVerVersion Parse(string versionString)
{
if (!TryParse(versionString, out var version))
{
throw new FormatException($"The string '{versionString}' was not recognized as a valid MinVer version");
}

return version;
}

/// <summary>
/// Converts the specified string representation of MinVer-compatible version to its <see cref="MinVerVersion" /> equivalent and returns a value that indicates whether the conversion succeeded.
/// </summary>
/// <param name="versionString">A string containing a string version to convert.</param>
/// <param name="version">When this method returns <see langword="true" />, contains the <see cref="MinVerVersion" /> value equivalent to the version contained in <paramref name="versionString">versionString</paramref>, if the conversion succeeded, or <see langword="null" /> if the conversion failed. The conversion fails if the <paramref name="versionString">versionString</paramref> parameter is null, is an empty string (""), or does not contain a valid string representation of a MinVer-compatible version.</param>
/// <returns><see langword="true" /> if the <paramref name="versionString">versionString</paramref> parameter was converted successfully; otherwise, <see langword="false" />.</returns>
public static bool TryParse(string versionString, out MinVerVersion version)
{
version = new MinVerVersion();

if (!TryParseAndFill(versionString, version))
{
version = null;
return false;
}

return true;
}

private static bool TryParseAndFill(string versionString, MinVerVersion version)
{
if (string.IsNullOrWhiteSpace(versionString))
{
return false;
}

var metaSplit = versionString.Split(new[] { '+' }, count: 2);
var preSplit = metaSplit[0].Split(new[] { '-' }, count: 2);
var rtmSplit = preSplit[0].Split('.');

if (rtmSplit.Length != 3)
{
return false;
}

var major = rtmSplit[0];
var minor = rtmSplit[1];
var patch = rtmSplit[2];
var preRelease = preSplit.ElementAtOrDefault(1);
var buildMetadata = metaSplit.ElementAtOrDefault(1);

if (!int.TryParse(major, NumberStyles.None, CultureInfo.InvariantCulture, out var majorInt)
|| !int.TryParse(minor, NumberStyles.None, CultureInfo.InvariantCulture, out var minorInt)
|| !int.TryParse(patch, NumberStyles.None, CultureInfo.InvariantCulture, out var patchInt))
{
return false;
}

version.Major = majorInt;
version.Minor = minorInt;
version.Patch = patchInt;
version.PreRelease = preRelease;
version.BuildMetadata = buildMetadata;

version.AssemblyVersion = FormattableString.Invariant($"{majorInt}.0.0.0");
version.FileVersion = FormattableString.Invariant($"{majorInt}.{minorInt}.{patchInt}.0");
version.Version = versionString;

return true;
}

/// <inheritdoc />
public override string ToString() => Version;

/// <inheritdoc />
// ReSharper disable once NonReadonlyMemberInGetHashCode
public override int GetHashCode() => Version.GetHashCode();

/// <inheritdoc />
Expand Down
43 changes: 41 additions & 2 deletions test/Cake.MinVer.Tests/MinVerVersionTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,11 @@ public void Should_Throw_If_Version_is_Null()
{
Action fixture = () =>
{
var _ = new MinVerVersion(version: null);
var _ = new MinVerVersion(versionString: null);
};

fixture.Should().ThrowExactly<ArgumentException>()
.And.ParamName.Should().Be("version");
.And.ParamName.Should().Be("versionString");
}

[Fact]
Expand Down Expand Up @@ -122,5 +122,44 @@ public void Should_Set_IsPreRelease()
new MinVerVersion("1.2.3-alpha.4").IsPreRelease.Should().Be(true);
new MinVerVersion("1.2.3-alpha.4+abcdefg").IsPreRelease.Should().Be(true);
}

[Theory]
[InlineData("1.2.3")]
[InlineData("1.2.3-alpha")]
[InlineData("1.2.3-alpha.4")]
[InlineData("1.2.3-alpha.4+abcdefg")]
public void Should_Parse_Valid_Version_Strings(string versionString)
{
var version1 = new MinVerVersion(versionString);
var version2 = MinVerVersion.Parse(versionString);
var result = MinVerVersion.TryParse(versionString, out var version3);

result.Should().BeTrue();

version1.Version.Should().Be(versionString);
version2.Version.Should().Be(versionString);
version3.Version.Should().Be(versionString);

version1.Should().BeEquivalentTo(version2);
version2.Should().BeEquivalentTo(version3);
}

[Theory]
[InlineData("x.2.3")]
[InlineData("1x2.3")]
[InlineData("1.x.3")]
[InlineData("1.2x3")]
[InlineData("1.2.x")]
[InlineData("1.2.3xalpha")]
public void Should_Not_Parse_Invalid_Version_Strings(string versionString)
{
Action version1Fixture = () => { var _ = new MinVerVersion(versionString); };
Action version2Fixture = () => { var _ = MinVerVersion.Parse(versionString); };
var result = MinVerVersion.TryParse(versionString, out _);

version1Fixture.Should().ThrowExactly<FormatException>();
version2Fixture.Should().ThrowExactly<FormatException>();
result.Should().BeFalse();
}
}
}

0 comments on commit 174bf20

Please sign in to comment.