public static bool TryParse(string text, [NotNullWhen(true)] out VersionInfo?version) { // check for version suffix (e.g "-rc1") var index = text.IndexOf('-'); string versionText; string suffix; if (index < 0) { versionText = text; suffix = ""; } else { versionText = text.Substring(0, index); suffix = text.Substring(index).TrimEnd('*'); } // parse parts of the version number int major; int minor; int build; int revision; if (int.TryParse(versionText, out major)) { // version is a single integral major version number minor = -1; build = -1; revision = -1; } else if (Version.TryParse(versionText, out var basicVersion)) { // assign parts of the parsed version information major = basicVersion.Major; minor = basicVersion.Minor; build = basicVersion.Build; revision = basicVersion.Revision; } else { version = null; return(false); } // if major version is 0 and minor is not 0, we encode the value as a fractional major version number if ((major == 0) && (minor != 0)) { var fractionalMajor = int.MinValue + minor - 1; version = new VersionInfo( fractionalMajor, (build != -1) ? (int?)build : null, (revision != -1) ? (int?)revision : null, suffix ); return(true); } // revision is not supported in this format since it requires 4 numbers to be stored if (revision != -1) { version = null; return(false); } version = new VersionInfo( major, (minor != -1) ? (int?)minor : null, (build != -1) ? (int?)build : null, suffix ); return(true); }
public bool IsGreaterOrEqualThanVersion(VersionInfo info, bool strict = false) => CompareToVersion(info, strict) >= 0;
public bool IsEqualToVersion(VersionInfo info, bool strict = false) => CompareToVersion(info, strict) == 0;
public int?CompareToVersion(VersionInfo other, bool strict = false) { if (object.ReferenceEquals(other, null)) { return(null); } if (strict) { // suffixes must match to be comparable in strict mode if (Suffix != other.Suffix) { return(null); } var result = (long)EncodedMajor - (long)other.EncodedMajor; if (result != 0) { return(Sign(result)); } result = (Minor ?? 0) - (other.Minor ?? 0); if (result != 0) { return(Sign(result)); } result = (Patch ?? 0) - (other.Patch ?? 0); if (result != 0) { return(Sign(result)); } return(0); } else { // version number dominates other comparisions var result = (long)EncodedMajor - (long)other.EncodedMajor; if (result != 0) { return(Sign(result)); } result = (Minor ?? 0) - (other.Minor ?? 0); if (result != 0) { return(Sign(result)); } result = (Patch ?? 0) - (other.Patch ?? 0); if (result != 0) { return(Sign(result)); } // a suffix indicates a pre-release version, which is always less than the stable version if ((Suffix == "") && (other.Suffix != "")) { return(1); } if ((Suffix != "") && (other.Suffix == "")) { return(-1); } if (Suffix == other.Suffix) { return(0); } // check if the suffixes have a trailing number that can be compared var shortestLength = Math.Min(Suffix.Length, other.Suffix.Length); var i = 1; for (; (i < shortestLength) && char.IsLetter(Suffix[i]) && (Suffix[i] == other.Suffix[i]); ++i) { ; } if ( int.TryParse(Suffix.Substring(i, Suffix.Length - i), out var leftSuffixValue) && int.TryParse(other.Suffix.Substring(i, other.Suffix.Length - i), out var rightSuffixVersion) ) { if (leftSuffixValue > rightSuffixVersion) { return(1); } if (leftSuffixValue < rightSuffixVersion) { return(-1); } return(0); } } // versions cannot be compared return(null); // local functions int Sign(long value) => (value < 0L) ? -1 : ((value > 0L) ? 1 : 0); }
public bool IsLessOrEqualThanVersion(VersionInfo info, bool strict = false) => CompareToVersion(info, strict) <= 0;
public static VersionInfo GetLambdaSharpAssemblyReferenceVersion(VersionInfo version) => version.GetMajorMinorVersion();
public static VersionInfo?FindLatestMatchingVersion(IEnumerable <VersionInfo> versionInfos, VersionInfo minVersion, Predicate <VersionInfo> validate) { var candidates = new List <VersionInfo>(versionInfos); while (candidates.Any()) { // find latest version var candidate = VersionInfo.Max(candidates) ?? throw new InvalidOperationException(); candidates.Remove(candidate); // check if latest version meets minimum version constraint; or if none are provided, the version cannot be a pre-release if ( ((minVersion != null) && minVersion.IsGreaterThanVersion(candidate)) || ((minVersion == null) && (validate == null) && candidate.IsPreRelease()) ) { continue; } // validate candidate if (validate?.Invoke(candidate) ?? true) { return(candidate); } } // not match found return(null); }
public static VersionInfo GetCoreServicesReferenceVersion(VersionInfo version) => version.GetMajorOnlyVersion();
public static bool IsModuleCoreVersionCompatibleWithTierVersion(VersionInfo moduleCoreVersion, VersionInfo tierVersion) => moduleCoreVersion.GetMajorOnlyVersion().IsEqualToVersion(tierVersion.GetMajorOnlyVersion());
public static bool IsModuleCoreVersionCompatibleWithToolVersion(VersionInfo moduleCoreVersion, VersionInfo toolVersion) => toolVersion.IsPreRelease() ? moduleCoreVersion.GetMajorOnlyVersion().WithoutSuffix().IsEqualToVersion(toolVersion.GetMajorOnlyVersion().WithoutSuffix()) && moduleCoreVersion.IsLessOrEqualThanVersion(toolVersion) : moduleCoreVersion.GetMajorOnlyVersion().IsEqualToVersion(toolVersion.GetMajorOnlyVersion());
//--- Class Methods --- public static bool IsTierVersionCompatibleWithToolVersion(VersionInfo tierVersion, VersionInfo toolVersion) => toolVersion.IsPreRelease() // allow a tool pre-release, next version to be compatible with any previously deployed tier version ? tierVersion.GetMajorOnlyVersion().WithoutSuffix().IsEqualToVersion(toolVersion.GetMajorOnlyVersion().WithoutSuffix()) && tierVersion.IsLessOrEqualThanVersion(toolVersion) // tool major version must match tier major version : tierVersion.GetMajorOnlyVersion().IsEqualToVersion(toolVersion.GetMajorOnlyVersion());
public static bool IsValidLambdaSharpAssemblyReferenceForToolVersion(VersionInfo toolVersion, string projectFramework, string lambdaSharpAssemblyVersion, out bool outdated) { // extract assembly version pattern without wildcard VersionWithSuffix libraryVersion; if (lambdaSharpAssemblyVersion.EndsWith(".*", StringComparison.Ordinal)) { libraryVersion = VersionWithSuffix.Parse(lambdaSharpAssemblyVersion.Substring(0, lambdaSharpAssemblyVersion.Length - 2)); } else { libraryVersion = VersionWithSuffix.Parse(lambdaSharpAssemblyVersion); } // compare based on selected framework bool valid; switch (projectFramework) { case "netstandard2.1": // .NET Standard 2.1 projects (Blazor) require 0.8.1.* or 0.8.2.* valid = (libraryVersion.Major == 0) && (libraryVersion.Minor == 8) && ( (libraryVersion.Build == 1) || (libraryVersion.Build == 2) ); break; case "netcoreapp2.1": // .NET Core 2.1 projects (Lambda) require 0.8.0.* or 0.8.1.* valid = (libraryVersion.Major == 0) && (libraryVersion.Minor == 8) && ( (libraryVersion.Build == 0) || (libraryVersion.Build == 1) ); break; case "netcoreapp3.1": // .NET Core 3.1 projects (Lambda) require 0.8.0.*, 0.8.1.*, or 0.8.2.* valid = (libraryVersion.Major == 0) && (libraryVersion.Minor == 8) && ( (libraryVersion.Build == 0) || (libraryVersion.Build == 1) || (libraryVersion.Build == 2) ); break; case "net5": case "net5.0": // .NET 5 projects require 0.8.2.* valid = (libraryVersion.Major == 0) && (libraryVersion.Minor == 8) && (libraryVersion.Build == 2); break; default: throw new VersionInfoCompatibilityUnsupportedFrameworkException(projectFramework); } outdated = valid && VersionInfo.From(libraryVersion, strict: false).IsLessThanVersion(toolVersion.GetMajorMinorVersion()); return(valid); }