From 982baf086575db150447d7aca5211b634bd13736 Mon Sep 17 00:00:00 2001 From: Omotola Akeredolu Date: Thu, 9 Feb 2023 16:52:56 -0800 Subject: [PATCH 1/2] Changed to upstream Semantic Versioning package --- Directory.Packages.props | 18 +- ...Microsoft.ComponentDetection.Common.csproj | 3 +- ...rosoft.ComponentDetection.Detectors.csproj | 6 +- .../rust/DependencySpecification.cs | 8 +- .../rust/SemVer/Comparator.cs | 228 ---------------- .../rust/SemVer/ComparatorSet.cs | 190 -------------- .../rust/SemVer/Desugarer.cs | 247 ------------------ .../rust/SemVer/PartialVersion.cs | 110 -------- .../rust/SemVer/Range.cs | 246 ----------------- .../rust/SemVer/cgmanifest.json | 14 - 10 files changed, 17 insertions(+), 1053 deletions(-) delete mode 100644 src/Microsoft.ComponentDetection.Detectors/rust/SemVer/Comparator.cs delete mode 100644 src/Microsoft.ComponentDetection.Detectors/rust/SemVer/ComparatorSet.cs delete mode 100644 src/Microsoft.ComponentDetection.Detectors/rust/SemVer/Desugarer.cs delete mode 100644 src/Microsoft.ComponentDetection.Detectors/rust/SemVer/PartialVersion.cs delete mode 100644 src/Microsoft.ComponentDetection.Detectors/rust/SemVer/Range.cs delete mode 100644 src/Microsoft.ComponentDetection.Detectors/rust/SemVer/cgmanifest.json diff --git a/Directory.Packages.props b/Directory.Packages.props index c5a94483d..3960e9888 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -1,13 +1,13 @@ - - - - Compile - - + + + + Compile + + - + @@ -30,7 +30,7 @@ - + @@ -45,5 +45,5 @@ - + diff --git a/src/Microsoft.ComponentDetection.Common/Microsoft.ComponentDetection.Common.csproj b/src/Microsoft.ComponentDetection.Common/Microsoft.ComponentDetection.Common.csproj index af7c4ea65..9f80c104e 100644 --- a/src/Microsoft.ComponentDetection.Common/Microsoft.ComponentDetection.Common.csproj +++ b/src/Microsoft.ComponentDetection.Common/Microsoft.ComponentDetection.Common.csproj @@ -1,10 +1,9 @@ - + - diff --git a/src/Microsoft.ComponentDetection.Detectors/Microsoft.ComponentDetection.Detectors.csproj b/src/Microsoft.ComponentDetection.Detectors/Microsoft.ComponentDetection.Detectors.csproj index 6b0313e14..0dc153a7b 100644 --- a/src/Microsoft.ComponentDetection.Detectors/Microsoft.ComponentDetection.Detectors.csproj +++ b/src/Microsoft.ComponentDetection.Detectors/Microsoft.ComponentDetection.Detectors.csproj @@ -1,4 +1,4 @@ - + @@ -6,7 +6,7 @@ - + @@ -17,7 +17,7 @@ - + diff --git a/src/Microsoft.ComponentDetection.Detectors/rust/DependencySpecification.cs b/src/Microsoft.ComponentDetection.Detectors/rust/DependencySpecification.cs index 9c6eb37c3..923de8708 100644 --- a/src/Microsoft.ComponentDetection.Detectors/rust/DependencySpecification.cs +++ b/src/Microsoft.ComponentDetection.Detectors/rust/DependencySpecification.cs @@ -1,9 +1,9 @@ -using System; +using System; using System.Collections.Generic; using Microsoft.ComponentDetection.Detectors.Rust.Contracts; -using Semver; -using Range = Microsoft.ComponentDetection.Detectors.Rust.SemVer.Range; +using Range = SemanticVersioning.Range; +using Version = SemanticVersioning.Version; namespace Microsoft.ComponentDetection.Detectors.Rust; @@ -42,7 +42,7 @@ public bool MatchesPackage(CargoPackage package) var allSatisfied = true; foreach (var range in ranges) { - if (SemVersion.TryParse(package.Version, out var sv)) + if (Version.TryParse(package.Version, out var sv)) { if (!range.IsSatisfied(sv)) { diff --git a/src/Microsoft.ComponentDetection.Detectors/rust/SemVer/Comparator.cs b/src/Microsoft.ComponentDetection.Detectors/rust/SemVer/Comparator.cs deleted file mode 100644 index 9e09af8f4..000000000 --- a/src/Microsoft.ComponentDetection.Detectors/rust/SemVer/Comparator.cs +++ /dev/null @@ -1,228 +0,0 @@ -// This file was copied from the SemanticVersioning package found at https://github.com/adamreeve/semver.net. -// The range logic from SemanticVersioning is needed in the Rust detector to supplement the Semver versioning package -// that is used elsewhere in this project. -// -// This is a temporary solution, so avoid using this functionality outside of the Rust detector. The following -// issues describe the problems with the SemanticVersioning package that make it problematic to use for versioning. -// https://github.com/adamreeve/semver.net/issues/46 -// https://github.com/adamreeve/semver.net/issues/47 - -using System; -using System.Text.RegularExpressions; -using Semver; - -namespace Microsoft.ComponentDetection.Detectors.Rust.SemVer; - -internal class Comparator : IEquatable -{ - private const string RangePattern = @" - \s* - ([=<>]*) # Comparator type (can be empty) - \s* - ([0-9a-zA-Z\-\+\.\*]+) # Version (potentially partial version) - \s* - "; - - private static readonly Regex RangePatternRegex = new Regex( - RangePattern, - RegexOptions.IgnorePatternWhitespace | RegexOptions.Compiled); - - public Comparator(string input) - { - var match = RangePatternRegex.Match(input); - if (!match.Success) - { - throw new ArgumentException(string.Format("Invalid comparator string: {0}", input)); - } - - this.ComparatorType = ParseComparatorType(match.Groups[1].Value); - var partialVersion = new PartialVersion(match.Groups[2].Value); - - if (!partialVersion.IsFull()) - { - // For Operator.Equal, partial versions are handled by the StarRange - // desugarer, and desugar to multiple comparators. - switch (this.ComparatorType) - { - // For <= with a partial version, eg. <=1.2.x, this - // means the same as < 1.3.0, and <=1.x means <2.0 - case Operator.LessThanOrEqual: - this.ComparatorType = Operator.LessThan; - if (!partialVersion.Major.HasValue) - { - // <=* means >=0.0.0 - this.ComparatorType = Operator.GreaterThanOrEqual; - this.Version = new SemVersion(0, 0, 0); - } - else if (!partialVersion.Minor.HasValue) - { - this.Version = new SemVersion(partialVersion.Major.Value + 1, 0, 0); - } - else - { - this.Version = new SemVersion(partialVersion.Major.Value, partialVersion.Minor.Value + 1, 0); - } - - break; - case Operator.GreaterThan: - this.ComparatorType = Operator.GreaterThanOrEqual; - if (!partialVersion.Major.HasValue) - { - // >* is unsatisfiable, so use <0.0.0 - this.ComparatorType = Operator.LessThan; - this.Version = new SemVersion(0, 0, 0); - } - else if (!partialVersion.Minor.HasValue) - { - // eg. >1.x -> >=2.0 - this.Version = new SemVersion(partialVersion.Major.Value + 1, 0, 0); - } - else - { - // eg. >1.2.x -> >=1.3 - this.Version = new SemVersion(partialVersion.Major.Value, partialVersion.Minor.Value + 1, 0); - } - - break; - - case Operator.Equal: - case Operator.LessThan: - case Operator.GreaterThanOrEqual: - default: - // <1.2.x means <1.2.0 - // >=1.2.x means >=1.2.0 - this.Version = partialVersion.ToZeroVersion(); - break; - } - } - else - { - this.Version = partialVersion.ToZeroVersion(); - } - } - - public Comparator(Operator comparatorType, SemVersion comparatorVersion) - { - this.ComparatorType = comparatorType; - this.Version = comparatorVersion ?? throw new NullReferenceException("Null comparator version"); - } - - public enum Operator - { - Equal = 0, - LessThan, - LessThanOrEqual, - GreaterThan, - GreaterThanOrEqual, - } - - public Operator ComparatorType { get; } - - public SemVersion Version { get; } - - public static Tuple TryParse(string input) - { - var match = RangePatternRegex.Match(input); - - return match.Success ? - Tuple.Create( - match.Length, - new Comparator(match.Value)) - : null; - } - - public bool IsSatisfied(SemVersion version) - { - return this.ComparatorType switch - { - Operator.Equal => version == this.Version, - Operator.LessThan => version < this.Version, - Operator.LessThanOrEqual => version <= this.Version, - Operator.GreaterThan => version > this.Version, - Operator.GreaterThanOrEqual => version >= this.Version, - _ => throw new InvalidOperationException("Comparator type not recognised."), - }; - } - - public bool Intersects(Comparator other) - { - static bool OperatorIsGreaterThan(Comparator c) => - c.ComparatorType == Operator.GreaterThan || - c.ComparatorType == Operator.GreaterThanOrEqual; - static bool OperatorIsLessThan(Comparator c) => - c.ComparatorType == Operator.LessThan || - c.ComparatorType == Operator.LessThanOrEqual; - static bool OperatorIncludesEqual(Comparator c) => - c.ComparatorType == Operator.GreaterThanOrEqual || - c.ComparatorType == Operator.Equal || - c.ComparatorType == Operator.LessThanOrEqual; - - if (this.Version > other.Version && (OperatorIsLessThan(this) || OperatorIsGreaterThan(other))) - { - return true; - } - - if (this.Version < other.Version && (OperatorIsGreaterThan(this) || OperatorIsLessThan(other))) - { - return true; - } - - if (this.Version == other.Version && ( - (OperatorIncludesEqual(this) && OperatorIncludesEqual(other)) || - (OperatorIsLessThan(this) && OperatorIsLessThan(other)) || - (OperatorIsGreaterThan(this) && OperatorIsGreaterThan(other)))) - { - return true; - } - - return false; - } - - public override string ToString() - { - string operatorString = null; - operatorString = this.ComparatorType switch - { - Operator.Equal => "=", - Operator.LessThan => "<", - Operator.LessThanOrEqual => "<=", - Operator.GreaterThan => ">", - Operator.GreaterThanOrEqual => ">=", - _ => throw new InvalidOperationException("Comparator type not recognised."), - }; - return string.Format("{0}{1}", operatorString, this.Version); - } - - public bool Equals(Comparator other) - { - if (other is null) - { - return false; - } - - return this.ComparatorType == other.ComparatorType && this.Version == other.Version; - } - - public override bool Equals(object other) - { - return this.Equals(other as Comparator); - } - - public override int GetHashCode() - { - return this.ToString().GetHashCode(); - } - - private static Operator ParseComparatorType(string input) - { - return input switch - { - "" or "=" => Operator.Equal, - "<" => Operator.LessThan, - "<=" => Operator.LessThanOrEqual, - ">" => Operator.GreaterThan, - ">=" => Operator.GreaterThanOrEqual, - _ => throw new ArgumentException(string.Format("Invalid comparator type: {0}", input)), - }; - } -} diff --git a/src/Microsoft.ComponentDetection.Detectors/rust/SemVer/ComparatorSet.cs b/src/Microsoft.ComponentDetection.Detectors/rust/SemVer/ComparatorSet.cs deleted file mode 100644 index e08b1de31..000000000 --- a/src/Microsoft.ComponentDetection.Detectors/rust/SemVer/ComparatorSet.cs +++ /dev/null @@ -1,190 +0,0 @@ -// This file was copied from the SemanticVersioning package found at https://github.com/adamreeve/semver.net. -// The range logic from SemanticVersioning is needed in the Rust detector to supplement the Semver versioning package -// that is used elsewhere in this project. -// -// This is a temporary solution, so avoid using this functionality outside of the Rust detector. The following -// issues describe the problems with the SemanticVersioning package that make it problematic to use for versioning. -// https://github.com/adamreeve/semver.net/issues/46 -// https://github.com/adamreeve/semver.net/issues/47 - -using System; -using System.Collections.Generic; -using System.Linq; -using Semver; - -namespace Microsoft.ComponentDetection.Detectors.Rust.SemVer; - -internal class ComparatorSet : IEquatable -{ - private readonly List comparators; - - public ComparatorSet(string spec) - { - this.comparators = new List { }; - - spec = spec.Trim(); - if (string.IsNullOrEmpty(spec)) - { - spec = "*"; - } - - var position = 0; - var end = spec.Length; - - while (position < end) - { - var iterStartPosition = position; - - // A comparator set might be an advanced range specifier - // like ~1.2.3, ^1.2, or 1.*. - // Check for these first before standard comparators: - foreach (var desugarer in new Func>[] - { - Desugarer.HyphenRange, - Desugarer.TildeRange, - Desugarer.CaretRange, - Desugarer.StarRange, - }) - { - var result = desugarer(spec[position..]); - if (result != null) - { - position += result.Item1; - this.comparators.AddRange(result.Item2); - } - } - - // Check for standard comparator with operator and version: - var comparatorResult = Comparator.TryParse(spec[position..]); - if (comparatorResult != null) - { - position += comparatorResult.Item1; - this.comparators.Add(comparatorResult.Item2); - } - - if (position == iterStartPosition) - { - // Didn't manage to read any valid comparators - throw new ArgumentException(string.Format("Invalid range specification: \"{0}\"", spec)); - } - } - } - - private ComparatorSet(IEnumerable comparators) => this.comparators = comparators.ToList(); - - public bool IsSatisfied(SemVersion version) - { - var satisfied = this.comparators.All(c => c.IsSatisfied(version)); - if (!string.IsNullOrEmpty(version.Prerelease)) - { - // If the version is a pre-release, then one of the - // comparators must have the same version and also include - // a pre-release tag. - return satisfied && this.comparators.Any(c => - !string.IsNullOrEmpty(c.Version.Prerelease) && - c.Version.Major == version.Major && - c.Version.Minor == version.Minor && - c.Version.Patch == version.Patch); - } - else - { - return satisfied; - } - } - - public ComparatorSet Intersect(ComparatorSet other) - { - static bool OperatorIsGreaterThan(Comparator c) => - c.ComparatorType == Comparator.Operator.GreaterThan || - c.ComparatorType == Comparator.Operator.GreaterThanOrEqual; - static bool OperatorIsLessThan(Comparator c) => - c.ComparatorType == Comparator.Operator.LessThan || - c.ComparatorType == Comparator.Operator.LessThanOrEqual; - var maxOfMins = - this.comparators.Concat(other.comparators) - .Where(OperatorIsGreaterThan) - .OrderByDescending(c => c.Version).FirstOrDefault(); - var minOfMaxs = - this.comparators.Concat(other.comparators) - .Where(OperatorIsLessThan) - .OrderBy(c => c.Version).FirstOrDefault(); - if (maxOfMins != null && minOfMaxs != null && !maxOfMins.Intersects(minOfMaxs)) - { - return null; - } - - // If there is an equality operator, check that it satisfies other operators - var equalityVersions = - this.comparators.Concat(other.comparators) - .Where(c => c.ComparatorType == Comparator.Operator.Equal) - .Select(c => c.Version) - .ToList(); - if (equalityVersions.Count > 1) - { - if (equalityVersions.Any(v => v != equalityVersions[0])) - { - return null; - } - } - - if (equalityVersions.Count > 0) - { - if (maxOfMins != null && !maxOfMins.IsSatisfied(equalityVersions[0])) - { - return null; - } - - if (minOfMaxs != null && !minOfMaxs.IsSatisfied(equalityVersions[0])) - { - return null; - } - - return new ComparatorSet( - new List - { - new Comparator(Comparator.Operator.Equal, equalityVersions[0]), - }); - } - - var comparators = new List(); - if (maxOfMins != null) - { - comparators.Add(maxOfMins); - } - - if (minOfMaxs != null) - { - comparators.Add(minOfMaxs); - } - - return comparators.Count > 0 ? new ComparatorSet(comparators) : null; - } - - public bool Equals(ComparatorSet other) - { - if (other is null) - { - return false; - } - - var thisSet = new HashSet(this.comparators); - return thisSet.SetEquals(other.comparators); - } - - public override bool Equals(object other) - { - return this.Equals(other as ComparatorSet); - } - - public override string ToString() - { - return string.Join(" ", this.comparators.Select(c => c.ToString()).ToArray()); - } - - public override int GetHashCode() - { - // XOR is commutative, so this hash code is independent - // of the order of comparators. - return this.comparators.Aggregate(0, (accum, next) => accum ^ next.GetHashCode()); - } -} diff --git a/src/Microsoft.ComponentDetection.Detectors/rust/SemVer/Desugarer.cs b/src/Microsoft.ComponentDetection.Detectors/rust/SemVer/Desugarer.cs deleted file mode 100644 index 3093b0966..000000000 --- a/src/Microsoft.ComponentDetection.Detectors/rust/SemVer/Desugarer.cs +++ /dev/null @@ -1,247 +0,0 @@ -// This file was copied from the SemanticVersioning package found at https://github.com/adamreeve/semver.net. -// The range logic from SemanticVersioning is needed in the Rust detector to supplement the Semver versioning package -// that is used elsewhere in this project. -// -// This is a temporary solution, so avoid using this functionality outside of the Rust detector. The following -// issues describe the problems with the SemanticVersioning package that make it problematic to use for versioning. -// https://github.com/adamreeve/semver.net/issues/46 -// https://github.com/adamreeve/semver.net/issues/47 - -using System; -using System.Text.RegularExpressions; -using Semver; - -namespace Microsoft.ComponentDetection.Detectors.Rust.SemVer; - -internal static class Desugarer -{ - private const string VersionChars = @"[0-9a-zA-Z\-\+\.\*]"; - - // tilde and caret requirements can't also have wildcards in them - private const string VersionCharsNoWildcard = @"[0-9a-zA-Z\-\+\.]"; - - private static readonly Regex TildePatternRegex = new Regex( - $@"^\s*~\s*({VersionCharsNoWildcard}+)\s*$", - RegexOptions.Compiled); - - // The caret is optional, as Cargo treats "x.y.z" like "^x.y.z": - // https://doc.rust-lang.org/cargo/reference/specifying-dependencies.html#specifying-dependencies-from-cratesio - private static readonly Regex CaretPatternRegex = new Regex( - $@"^\s*\^?\s*({VersionCharsNoWildcard}+)\s*$", - RegexOptions.Compiled); - - private static readonly Regex HyphenPatternRegex = new Regex( - $@"^\s*({VersionChars}+)\s+\-\s+({VersionChars}+)\s*", - RegexOptions.Compiled); - - private static readonly Regex StarPatternRegex = new Regex( - $@"^\s*=?\s*({VersionChars}+)\s*", - RegexOptions.Compiled); - - // Allows patch-level changes if a minor version is specified - // on the comparator. Allows minor-level changes if not. - public static Tuple TildeRange(string spec) - { - var match = TildePatternRegex.Match(spec); - if (!match.Success) - { - return null; - } - - SemVersion minVersion = null; - SemVersion maxVersion = null; - - var version = new PartialVersion(match.Groups[1].Value); - if (version.Minor.HasValue) - { - // Doesn't matter whether patch version is null or not, - // the logic is the same, min patch version will be zero if null. - minVersion = version.ToZeroVersion(); - maxVersion = new SemVersion(version.Major.Value, version.Minor.Value + 1, 0); - } - else - { - minVersion = version.ToZeroVersion(); - maxVersion = new SemVersion(version.Major.Value + 1, 0, 0); - } - - return Tuple.Create( - match.Length, - MinMaxComparators(minVersion, maxVersion)); - } - - // Allows changes that do not modify the left-most non-zero digit - // in the [major, minor, patch] tuple. - public static Tuple CaretRange(string spec) - { - var match = CaretPatternRegex.Match(spec); - if (!match.Success) - { - return null; - } - - SemVersion minVersion = null; - SemVersion maxVersion = null; - - var version = new PartialVersion(match.Groups[1].Value); - - if (version.Major.Value > 0) - { - // Don't allow major version change - minVersion = version.ToZeroVersion(); - maxVersion = new SemVersion(version.Major.Value + 1, 0, 0); - } - else if (!version.Minor.HasValue) - { - // Don't allow major version change, even if it's zero - minVersion = version.ToZeroVersion(); - maxVersion = new SemVersion(version.Major.Value + 1, 0, 0); - } - else if (!version.Patch.HasValue) - { - // Don't allow minor version change, even if it's zero - minVersion = version.ToZeroVersion(); - maxVersion = new SemVersion(0, version.Minor.Value + 1, 0); - } - else if (version.Minor > 0) - { - // Don't allow minor version change - minVersion = version.ToZeroVersion(); - maxVersion = new SemVersion(0, version.Minor.Value + 1, 0); - } - else - { - // Only patch non-zero, don't allow patch change - minVersion = version.ToZeroVersion(); - maxVersion = new SemVersion(0, 0, version.Patch.Value + 1); - } - - return Tuple.Create( - match.Length, - MinMaxComparators(minVersion, maxVersion)); - } - - public static Tuple HyphenRange(string spec) - { - var match = HyphenPatternRegex.Match(spec); - if (!match.Success) - { - return null; - } - - PartialVersion minPartialVersion = null; - PartialVersion maxPartialVersion = null; - - // Parse versions from lower and upper ranges, which might - // be partial versions. - try - { - minPartialVersion = new PartialVersion(match.Groups[1].Value); - maxPartialVersion = new PartialVersion(match.Groups[2].Value); - } - catch (ArgumentException) - { - return null; - } - - // Lower range has any non-supplied values replaced with zero - var minVersion = minPartialVersion.ToZeroVersion(); - - var maxOperator = maxPartialVersion.IsFull() - ? Comparator.Operator.LessThanOrEqual : Comparator.Operator.LessThan; - - SemVersion maxVersion = null; - - // Partial upper range means supplied version values can't change - if (!maxPartialVersion.Major.HasValue) - { - // eg. upper range = "*", then maxVersion remains null - // and there's only a minimum - } - else if (!maxPartialVersion.Minor.HasValue) - { - maxVersion = new SemVersion(maxPartialVersion.Major.Value + 1, 0, 0); - } - else if (!maxPartialVersion.Patch.HasValue) - { - maxVersion = new SemVersion(maxPartialVersion.Major.Value, maxPartialVersion.Minor.Value + 1, 0); - } - else - { - // Fully specified max version - maxVersion = maxPartialVersion.ToZeroVersion(); - } - - return Tuple.Create( - match.Length, - MinMaxComparators(minVersion, maxVersion, maxOperator)); - } - - public static Tuple StarRange(string spec) - { - var match = StarPatternRegex.Match(spec); - - if (!match.Success) - { - return null; - } - - PartialVersion version = null; - try - { - version = new PartialVersion(match.Groups[1].Value); - } - catch (ArgumentException) - { - return null; - } - - // If partial version match is actually a full version, - // then this isn't a star range, so return null. - if (version.IsFull()) - { - return null; - } - - SemVersion minVersion = null; - SemVersion maxVersion = null; - - if (!version.Major.HasValue) - { - minVersion = version.ToZeroVersion(); - - // no max version - } - else if (!version.Minor.HasValue) - { - minVersion = version.ToZeroVersion(); - maxVersion = new SemVersion(version.Major.Value + 1, 0, 0); - } - else - { - minVersion = version.ToZeroVersion(); - maxVersion = new SemVersion(version.Major.Value, version.Minor.Value + 1, 0); - } - - return Tuple.Create( - match.Length, - MinMaxComparators(minVersion, maxVersion)); - } - - private static Comparator[] MinMaxComparators(SemVersion minVersion, SemVersion maxVersion, Comparator.Operator maxOperator = Comparator.Operator.LessThan) - { - var minComparator = new Comparator( - Comparator.Operator.GreaterThanOrEqual, - minVersion); - if (maxVersion == null) - { - return new[] { minComparator }; - } - else - { - var maxComparator = new Comparator( - maxOperator, maxVersion); - return new[] { minComparator, maxComparator }; - } - } -} diff --git a/src/Microsoft.ComponentDetection.Detectors/rust/SemVer/PartialVersion.cs b/src/Microsoft.ComponentDetection.Detectors/rust/SemVer/PartialVersion.cs deleted file mode 100644 index b5f9bc4c1..000000000 --- a/src/Microsoft.ComponentDetection.Detectors/rust/SemVer/PartialVersion.cs +++ /dev/null @@ -1,110 +0,0 @@ -// This file was copied from the SemanticVersioning package found at https://github.com/adamreeve/semver.net. -// The range logic from SemanticVersioning is needed in the Rust detector to supplement the Semver versioning package -// that is used elsewhere in this project. -// -// This is a temporary solution, so avoid using this functionality outside of the Rust detector. The following -// issues describe the problems with the SemanticVersioning package that make it problematic to use for versioning. -// https://github.com/adamreeve/semver.net/issues/46 -// https://github.com/adamreeve/semver.net/issues/47 - -using System; -using System.Linq; -using System.Text.RegularExpressions; -using Semver; - -namespace Microsoft.ComponentDetection.Detectors.Rust.SemVer; - -// A version that might not have a minor or patch -// number, for use in ranges like "^1.2" or "2.x" -internal class PartialVersion -{ - private static readonly Regex VersionRegex = new Regex( - @"^ - [v=\s]* - (\d+|[Xx\*]) # major version - ( - \. - (\d+|[Xx\*]) # minor version - ( - \. - (\d+|[Xx\*]) # patch version - (\-?([0-9A-Za-z\-\.]+))? # pre-release version - (\+([0-9A-Za-z\-\.]+))? # build version (ignored) - )? - )? - $", - RegexOptions.Compiled | RegexOptions.IgnorePatternWhitespace); - - public PartialVersion(string input) - { - string[] xValues = { "X", "x", "*" }; - - if (string.IsNullOrEmpty(input.Trim())) - { - // Empty input means any version - return; - } - - var match = VersionRegex.Match(input); - if (!match.Success) - { - throw new ArgumentException(string.Format("Invalid version string: \"{0}\"", input)); - } - - if (xValues.Contains(match.Groups[1].Value)) - { - this.Major = null; - } - else - { - this.Major = int.Parse(match.Groups[1].Value); - } - - if (match.Groups[2].Success) - { - if (xValues.Contains(match.Groups[3].Value)) - { - this.Minor = null; - } - else - { - this.Minor = int.Parse(match.Groups[3].Value); - } - } - - if (match.Groups[4].Success) - { - if (xValues.Contains(match.Groups[5].Value)) - { - this.Patch = null; - } - else - { - this.Patch = int.Parse(match.Groups[5].Value); - } - } - - if (match.Groups[6].Success) - { - this.PreRelease = match.Groups[7].Value; - } - } - - public int? Major { get; set; } - - public int? Minor { get; set; } - - public int? Patch { get; set; } - - public string PreRelease { get; set; } - - public SemVersion ToZeroVersion() - { - return new SemVersion(this.Major ?? 0, this.Minor ?? 0, this.Patch ?? 0, this.PreRelease); - } - - public bool IsFull() - { - return this.Major.HasValue && this.Minor.HasValue && this.Patch.HasValue; - } -} diff --git a/src/Microsoft.ComponentDetection.Detectors/rust/SemVer/Range.cs b/src/Microsoft.ComponentDetection.Detectors/rust/SemVer/Range.cs deleted file mode 100644 index 069db0f35..000000000 --- a/src/Microsoft.ComponentDetection.Detectors/rust/SemVer/Range.cs +++ /dev/null @@ -1,246 +0,0 @@ -// This file was copied from the SemanticVersioning package found at https://github.com/adamreeve/semver.net. -// The range logic from SemanticVersioning is needed in the Rust detector to supplement the Semver versioning package -// that is used elsewhere in this project. -// -// This is a temporary solution, so avoid using this functionality outside of the Rust detector. The following -// issues describe the problems with the SemanticVersioning package that make it problematic to use for versioning. -// https://github.com/adamreeve/semver.net/issues/46 -// https://github.com/adamreeve/semver.net/issues/47 - -using System; -using System.Collections.Generic; -using System.Linq; -using Semver; - -namespace Microsoft.ComponentDetection.Detectors.Rust.SemVer; - -/// -/// Specifies valid versions. -/// -public class Range : IEquatable -{ - private readonly ComparatorSet[] comparatorSets; - - private readonly string rangeSpec; - - /// - /// 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. - public Range(string rangeSpec, bool loose = false) - { - this.rangeSpec = rangeSpec; - var comparatorSetSpecs = rangeSpec.Split(new[] { "||" }, StringSplitOptions.None); - this.comparatorSets = comparatorSetSpecs.Select(s => new ComparatorSet(s)).ToArray(); - } - - private Range(IEnumerable comparatorSets) - { - this.comparatorSets = comparatorSets.ToArray(); - this.rangeSpec = string.Join(" || ", comparatorSets.Select(cs => cs.ToString()).ToArray()); - } - - public static bool operator ==(Range a, Range b) - { - if (a is null) - { - return b is null; - } - - return a.Equals(b); - } - - public static bool operator !=(Range a, Range b) => !(a == b); - - // Static convenience methods - - /// - /// Determine whether the given version satisfies a given range. - /// With an invalid version this method returns false. - /// - /// The range specification. - /// 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) - { - var range = new Range(rangeSpec); - return range.IsSatisfied(versionString); - } - - /// - /// Return the set of version strings that satisfy a given range. - /// Invalid version specifications are skipped. - /// - /// The range specification. - /// 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) - { - var range = new Range(rangeSpec); - return range.Satisfying(versions); - } - - /// - /// Return the maximum version that satisfies a given range. - /// - /// The range specification. - /// 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 static string MaxSatisfying(string rangeSpec, IEnumerable versionStrings, bool loose = false) - { - var range = new Range(rangeSpec); - return range.MaxSatisfying(versionStrings); - } - - private IEnumerable ValidVersions(IEnumerable versionStrings, bool loose) - { - foreach (var v in versionStrings) - { - SemVersion version = null; - try - { - SemVersion.TryParse(v, out version, loose); - } - catch (ArgumentException) - { - // Skip - } - - if (version != null) - { - yield return version; - } - } - } - - /// - /// Determine whether the given version satisfies this range. - /// - /// The version to check. - /// true if the range is satisfied by the version. - public bool IsSatisfied(SemVersion version) - { - return this.comparatorSets.Any(s => s.IsSatisfied(version)); - } - - /// - /// Determine whether the given version satisfies this range. - /// With an invalid version this method returns false. - /// - /// 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) - { - try - { - SemVersion.TryParse(versionString, out var version, loose); - return this.IsSatisfied(version); - } - catch (ArgumentException) - { - return false; - } - } - - /// - /// Return the set of versions that satisfy this range. - /// - /// The versions to check. - /// An IEnumerable of satisfying versions. - public IEnumerable Satisfying(IEnumerable versions) - { - return versions.Where(this.IsSatisfied); - } - - /// - /// Return the set of version strings that satisfy this range. - /// Invalid version specifications are skipped. - /// - /// 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) - { - return versions.Where(v => this.IsSatisfied(v, loose)); - } - - /// - /// Return the maximum version that satisfies this range. - /// - /// The versions to select from. - /// The maximum satisfying version, or null if no versions satisfied this range. - public SemVersion MaxSatisfying(IEnumerable versions) - { - return this.Satisfying(versions).Max(); - } - - /// - /// Return the maximum version that satisfies this range. - /// - /// 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) - { - var versions = this.ValidVersions(versionStrings, loose); - var maxVersion = this.MaxSatisfying(versions); - return maxVersion?.ToString(); - } - - /// - /// Calculate the intersection between two ranges. - /// - /// The Range to intersect this Range with. - /// The Range intersection. - public Range Intersect(Range other) - { - var allIntersections = this.comparatorSets.SelectMany( - thisCs => other.comparatorSets.Select(thisCs.Intersect)) - .Where(cs => cs != null).ToList(); - - if (allIntersections.Count == 0) - { - return new Range("<0.0.0"); - } - - return new Range(allIntersections); - } - - /// - /// Returns the range specification string used when constructing this range. - /// - /// The range string. - public override string ToString() - { - return this.rangeSpec; - } - - public bool Equals(Range other) - { - if (other is null) - { - return false; - } - - var thisSet = new HashSet(this.comparatorSets); - return thisSet.SetEquals(other.comparatorSets); - } - - public override bool Equals(object other) - { - return this.Equals(other as Range); - } - - public override int GetHashCode() - { - // XOR is commutative, so this hash code is independent - // of the order of comparators. - return this.comparatorSets.Aggregate(0, (accum, next) => accum ^ next.GetHashCode()); - } -} diff --git a/src/Microsoft.ComponentDetection.Detectors/rust/SemVer/cgmanifest.json b/src/Microsoft.ComponentDetection.Detectors/rust/SemVer/cgmanifest.json deleted file mode 100644 index 076add2c0..000000000 --- a/src/Microsoft.ComponentDetection.Detectors/rust/SemVer/cgmanifest.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "Registrations": [ - { - "Component": { - "Type": "git", - "git": { - "RepositoryUrl": "https://github.com/adamreeve/semver.net/", - "CommitHash": "efe3e2e87276ba6b231fc73898ed1651e584f354" - } - }, - "DevelopmentDependency": false - } - ] -} \ No newline at end of file From 8024472a6d35a8464c8f5c2c50d8e1e14efc0c31 Mon Sep 17 00:00:00 2001 From: Omotola Akeredolu Date: Thu, 9 Feb 2023 17:02:58 -0800 Subject: [PATCH 2/2] updated to latest semantic versioning version 2.0.2 --- Directory.Packages.props | 78 ++++++++++++++++++++-------------------- 1 file changed, 38 insertions(+), 40 deletions(-) diff --git a/Directory.Packages.props b/Directory.Packages.props index 3960e9888..7e2d47509 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -1,49 +1,47 @@ - Compile - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + \ No newline at end of file