| File: Utilities\VersionUtilities.cs | Web Access |
| Project: src\msbuild\src\Framework\Microsoft.Build.Framework.csproj (Microsoft.Build.Framework) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using System; using System.Collections; using System.Collections.Generic; #nullable disable namespace Microsoft.Build.Shared { /// <summary> /// Set of methods to deal with versions in the tasks /// </summary> internal static class VersionUtilities { /// <summary> /// Convert a version number like 0.0.0.0 to a Version instance. /// The method will return null if the string is not a valid value /// </summary> /// <param name="version">Version string to convert to a version object</param> internal static Version ConvertToVersion(string version) { return ConvertToVersion(version, false); } /// <summary> /// Go though an enumeration and create a sorted list of strings which can be parsed as versions. Keep around the original /// string because it may contain a v and this would be required to create the correct path on disk if the string was part of a path. /// </summary> internal static SortedDictionary<Version, List<string>> GatherVersionStrings(Version targetPlatformVersion, IEnumerable versions) { SortedDictionary<Version, List<string>> versionValues = new SortedDictionary<Version, List<string>>(ReverseVersionGenericComparer.Comparer); // Loop over versions from registry. foreach (string version in versions) { if (version.Length > 0) { Version candidateVersion = VersionUtilities.ConvertToVersion(version); if (candidateVersion != null && (targetPlatformVersion == null || (candidateVersion <= targetPlatformVersion))) { if (versionValues.TryGetValue(candidateVersion, out List<string> versionList)) { if (!versionList.Contains(version)) { versionList.Add(version); } } else { versionValues.Add(candidateVersion, new List<string>() { version }); } } } } return versionValues; } /// <summary> /// Convert a version number like 0.0.0.0 to a Version instance. /// </summary> /// <param name="version"></param> /// <param name="throwException">Should we use Parse to TryParse (parse means we throw an exception, tryparse means we will not).</param> internal static Version ConvertToVersion(string version, bool throwException) { if (version.Length > 0 && (version[0] == 'v' || version[0] == 'V')) { version = version.Substring(1); } // Versions must have at least a Major and a Minor (e.g. 10.0), so if it's // just one number without a decimal, add a decimal and a 0. Random strings // like "tmp" will be filtered out in the Parse() or TryParse() steps if (version.IndexOf('.') == -1) { version += ".0"; } Version result; if (throwException) { result = Version.Parse(version); } else { if (!Version.TryParse(version, out result)) { return null; } } return result; } } internal sealed class ReverseStringGenericComparer : IComparer<string> { /// <summary> /// Static accessor for a ReverseVersionGenericComparer /// </summary> internal static readonly ReverseStringGenericComparer Comparer = new ReverseStringGenericComparer(); /// <summary> /// The Compare implements a reverse comparison /// </summary> int IComparer<string>.Compare(string x, string y) { // Reverse the sign of the return value. return StringComparer.OrdinalIgnoreCase.Compare(y, x); } } internal sealed class ReverseVersionGenericComparer : IComparer<Version> { /// <summary> /// Static accessor for a ReverseVersionGenericComparer /// </summary> internal static readonly ReverseVersionGenericComparer Comparer = new ReverseVersionGenericComparer(); /// <summary> /// The Compare implements a reverse comparison /// </summary> int IComparer<Version>.Compare(Version x, Version y) { // Reverse the sign of the return value. return y.CompareTo(x); } } }