diff --git a/src/SemVer/Range.cs b/src/SemVer/Range.cs index 40e9578..50e1895 100644 --- a/src/SemVer/Range.cs +++ b/src/SemVer/Range.cs @@ -19,10 +19,10 @@ public class Range : IEquatable /// The range specification string. /// When true, be more forgiving of some invalid version specifications. /// Thrown when the range specification is invalid. - public Range(string rangeSpec, bool loose=false) + public Range(string rangeSpec, bool loose = false) { _rangeSpec = rangeSpec; - var comparatorSetSpecs = rangeSpec.Split(new [] {"||"}, StringSplitOptions.None); + var comparatorSetSpecs = rangeSpec.Split(new[] { "||" }, StringSplitOptions.None); _comparatorSets = comparatorSetSpecs.Select(s => new ComparatorSet(s)).ToArray(); } @@ -49,7 +49,7 @@ public bool IsSatisfied(Version version) /// The version to check. /// When true, be more forgiving of some invalid version specifications. /// true if the range is satisfied by the version. - public bool IsSatisfied(string versionString, bool loose=false) + public bool IsSatisfied(string versionString, bool loose = false) { try { @@ -79,7 +79,7 @@ public IEnumerable Satisfying(IEnumerable versions) /// The version strings to check. /// When true, be more forgiving of some invalid version specifications. /// An IEnumerable of satisfying version strings. - public IEnumerable Satisfying(IEnumerable versions, bool loose=false) + public IEnumerable Satisfying(IEnumerable versions, bool loose = false) { return versions.Where(v => IsSatisfied(v, loose)); } @@ -100,7 +100,7 @@ public Version MaxSatisfying(IEnumerable versions) /// The version strings to select from. /// When true, be more forgiving of some invalid version specifications. /// The maximum satisfying version string, or null if no versions satisfied this range. - public string MaxSatisfying(IEnumerable versionStrings, bool loose=false) + public string MaxSatisfying(IEnumerable versionStrings, bool loose = false) { var versions = ValidVersions(versionStrings, loose); var maxVersion = MaxSatisfying(versions); @@ -180,7 +180,7 @@ public override int GetHashCode() /// The version to check. /// When true, be more forgiving of some invalid version specifications. /// true if the range is satisfied by the version. - public static bool IsSatisfied(string rangeSpec, string versionString, bool loose=false) + public static bool IsSatisfied(string rangeSpec, string versionString, bool loose = false) { var range = new Range(rangeSpec); return range.IsSatisfied(versionString); @@ -194,7 +194,7 @@ public static bool IsSatisfied(string rangeSpec, string versionString, bool loos /// The version strings to check. /// When true, be more forgiving of some invalid version specifications. /// An IEnumerable of satisfying version strings. - public static IEnumerable Satisfying(string rangeSpec, IEnumerable versions, bool loose=false) + public static IEnumerable Satisfying(string rangeSpec, IEnumerable versions, bool loose = false) { var range = new Range(rangeSpec); return range.Satisfying(versions); @@ -207,12 +207,52 @@ public static IEnumerable Satisfying(string rangeSpec, IEnumerableThe version strings to select from. /// When true, be more forgiving of some invalid version specifications. /// The maximum satisfying version string, or null if no versions satisfied this range. - public static string MaxSatisfying(string rangeSpec, IEnumerable versionStrings, bool loose=false) + public static string MaxSatisfying(string rangeSpec, IEnumerable versionStrings, bool loose = false) { var range = new Range(rangeSpec); return range.MaxSatisfying(versionStrings); } + /// + /// Construct a new range from a range specification. + /// + /// The range specification string. + /// When true, be more forgiving of some invalid version specifications. + /// Thrown when the range specification is invalid. + /// The Range + public static Range Parse(string rangeSpec, bool loose = false) + => new Range(rangeSpec, loose); + + /// + /// Try to construct a new range from a range specification. + /// + /// The range specification string. + /// The Range, or null when parse fails. + /// A boolean indicating success of the parse operation. + public static bool TryParse(string rangeSpec, out Range result) + => TryParse(rangeSpec, loose: false, out result); + + /// + /// Try to construct a new range from a range specification. + /// + /// The range specification string. + /// When true, be more forgiving of some invalid version specifications. + /// The Range, or null when parse fails. + /// A boolean indicating success of the parse operation. + public static bool TryParse(string rangeSpec, bool loose, out Range result) + { + try + { + result = Parse(rangeSpec, loose); + return true; + } + catch + { + result = null; + return false; + } + } + private IEnumerable ValidVersions(IEnumerable versionStrings, bool loose) { foreach (var v in versionStrings) diff --git a/src/SemVer/Version.cs b/src/SemVer/Version.cs index 6165e61..dcc83ec 100644 --- a/src/SemVer/Version.cs +++ b/src/SemVer/Version.cs @@ -40,7 +40,7 @@ public class Version : IComparable, IComparable, IEquatable /// /// The build string, or null for no build version. /// - public string Build { get {return _build; } } + public string Build { get { return _build; } } private static Regex strictRegex = new Regex(@"^ \s*v? @@ -74,7 +74,7 @@ public class Version : IComparable, IComparable, IEquatable /// The version string. /// When true, be more forgiving of some invalid version specifications. /// Thrown when the version string is invalid. - public Version(string input, bool loose=false) + public Version(string input, bool loose = false) { _inputString = input; @@ -213,7 +213,7 @@ public int CompareTo(object obj) throw new ArgumentException("Object is not a Version"); } } - + // Implement IComparable public int CompareTo(Version other) { @@ -245,6 +245,48 @@ public override bool Equals(object other) return Equals(other as Version); } + // Static convenience methods + + /// + /// Construct a new semantic version from a version string. + /// + /// The version string. + /// When true, be more forgiving of some invalid version specifications. + /// Thrown when the version string is invalid. + /// The Version + public static Version Parse(string input, bool loose = false) + => new Version(input, loose); + + /// + /// Try to construct a new semantic version from a version string. + /// + /// The version string. + /// The Version, or null when parse fails. + /// A boolean indicating success of the parse operation. + public static bool TryParse(string input, out Version result) + => TryParse(input, loose: false, out result); + + /// + /// Try to construct a new semantic version from a version string. + /// + /// The version string. + /// When true, be more forgiving of some invalid version specifications. + /// The Version, or null when parse fails. + /// A boolean indicating success of the parse operation. + public static bool TryParse(string input, bool loose, out Version result) + { + try + { + result = Parse(input, loose); + return true; + } + catch + { + result = null; + return false; + } + } + public static bool operator ==(Version a, Version b) { if (ReferenceEquals(a, null)) diff --git a/test/SemVer.Tests/TryParse.cs b/test/SemVer.Tests/TryParse.cs new file mode 100644 index 0000000..276962c --- /dev/null +++ b/test/SemVer.Tests/TryParse.cs @@ -0,0 +1,53 @@ +using Xunit; + +namespace SemVer.Tests +{ + public class TryParse + { + [Theory] + [InlineData("1.0.0", false, true)] + [InlineData("v 1.2.3", true, true)] + [InlineData("Not SemVer", false, false)] + public void VersionTryParse(string input, bool loose, bool expectedResult) + { + //Given + + //When + var success = Version.TryParse(input, loose, out var version); + + //Then + Assert.Equal(expectedResult, success); + if (success) + { + Assert.NotNull(version); + } + else + { + Assert.Null(version); + } + } + + + [Theory] + [InlineData("~1.0.0", false, true)] + [InlineData("< 1", true, true)] + [InlineData("Not SemVer Range", false, false)] + public void RangeTryParse(string rangeSpec, bool loose, bool expectedResult) + { + //Given + + //When + var success = Range.TryParse(rangeSpec, loose, out var range); + + //Then + Assert.Equal(expectedResult, success); + if (success) + { + Assert.NotNull(range); + } + else { + Assert.Null(range); + } + } + } +} \ No newline at end of file