private static int CompareOneWay(IVersionComparer comparer, string version1, string version2) { // Arrange var a = NuGetVersion.Parse(version1); var b = NuGetVersion.Parse(version2); var c = SemanticVersion.Parse(version1); var d = SemanticVersion.Parse(version2); // Act var results = new List<int>(); results.Add(comparer.Compare(a, b)); results.Add(comparer.Compare(a, d)); results.Add(comparer.Compare(c, b)); results.Add(comparer.Compare(c, d)); // Assert Assert.True(results.FindAll(x => x == results[0]).Count == results.Count); return results[0]; }
/// <summary> /// Determines if an NuGetVersion meets the requirements using the version comparer. /// </summary> /// <param name="version">SemVer to compare.</param> /// <param name="comparer">Version comparer used to determine if the version criteria is met.</param> /// <returns>True if the given version meets the version requirements.</returns> public bool Satisfies(NuGetVersion version, IVersionComparer comparer) { if (version == null) { throw new ArgumentNullException("version"); } // Determine if version is in the given range using the comparer. bool condition = true; if (HasLowerBound) { if (IsMinInclusive) { condition &= comparer.Compare(MinVersion, version) <= 0; } else { condition &= comparer.Compare(MinVersion, version) < 0; } } if (HasUpperBound) { if (IsMaxInclusive) { condition &= comparer.Compare(MaxVersion, version) >= 0; } else { condition &= comparer.Compare(MaxVersion, version) > 0; } } if (!IncludePrerelease) { condition &= IsPrerelease(version) != true; } return(condition); }
private static int CompareOneWay(IVersionComparer comparer, string version1, string version2) { // Arrange var a = NuGetVersion.Parse(version1); var b = NuGetVersion.Parse(version2); var c = SemanticVersion.Parse(version1); var d = SemanticVersion.Parse(version2); // Act var results = new List <int>(); results.Add(comparer.Compare(a, b)); results.Add(comparer.Compare(a, d)); results.Add(comparer.Compare(c, b)); results.Add(comparer.Compare(c, d)); // Assert Assert.True(results.FindAll(x => x == results[0]).Count == results.Count); return(results[0]); }
private static bool EqualsOneWayWithNuGetVersion(IVersionComparer comparer, string version1, string version2) { // Arrange var a = NuGetVersion.Parse(version1); var b = NuGetVersion.Parse(version2); // Act var match = comparer.Compare(a, b) == 0; match &= comparer.Equals(a, b); match &= comparer.GetHashCode(a) == comparer.GetHashCode(b); return(match); }
public async Task AnalyzeAsync(IProject project, IDependencyAnalysisState state, CancellationToken token) { if (project is null) { throw new ArgumentNullException(nameof(project)); } if (state is null) { throw new ArgumentNullException(nameof(state)); } if (!state.TargetFrameworks.Any(tfm => tfm.IsWindows)) { return; } if (await _transitiveIdentifier.IsTransitiveDependencyAsync(PackageName, project, token).ConfigureAwait(false)) { _logger.LogDebug("{PackageName} already referenced transitively", PackageName); return; } var latestVersion = await _loader.GetLatestVersionAsync(PackageName, state.TargetFrameworks, new(), token).ConfigureAwait(false); if (latestVersion is null) { _logger.LogWarning("Could not find {PackageName}", latestVersion); return; } if (project.NuGetReferences.TryGetPackageByName(PackageName, out var existing)) { if (_comparer.Compare(existing.Version, latestVersion.Version) >= 0) { return; } state.Packages.Remove(existing, new OperationDetails()); } var logMessage = SR.Format("Adding {0} {1} helps with speeding up the upgrade process for Windows-based APIs", PackageName, latestVersion.Version); _logger.LogInformation(logMessage); state.Packages.Add(new NuGetReference(PackageName, latestVersion.Version), new OperationDetails { Details = new[] { logMessage } }); }
public async Task <PackageAnalysisState> AnalyzeAsync(IProject project, PackageAnalysisState state, CancellationToken token) { if (project is null) { throw new ArgumentNullException(nameof(project)); } if (state is null) { throw new ArgumentNullException(nameof(state)); } if (!project.TargetFrameworks.Any(tfm => tfm.IsWindows)) { return(state); } var references = await project.GetNuGetReferencesAsync(token).ConfigureAwait(false); if (references.IsTransitivelyAvailable(PackageName)) { _logger.LogDebug("{PackageName} already referenced transitively", PackageName); return(state); } var latestVersion = await _loader.GetLatestVersionAsync(PackageName, false, null, token).ConfigureAwait(false); if (latestVersion is null) { _logger.LogWarning("Could not find {PackageName}", latestVersion); return(state); } if (references.TryGetPackageByName(PackageName, out var existing)) { if (_comparer.Compare(existing.Version, latestVersion.Version) >= 0) { return(state); } state.PackagesToRemove.Add(existing); } _logger.LogInformation("Adding {PackageName} {Version}", PackageName, latestVersion.Version); state.PackagesToAdd.Add(new NuGetReference(PackageName, latestVersion.Version)); return(state); }
private static bool DoesHaveMinimumXamarinVersion(IProject project, IVersionComparer comparer) { var packageReferences = project.NuGetReferences.PackageReferences; foreach (var package in packageReferences) { if (package.Name == "Xamarin.Forms") { if (comparer.Compare(package.Version, MINIMUM_XAMARIN_VERSION) > 0) { return(true); } } } return(false); }
/// <summary> /// Determines whether a packages given contain a given package name and version. /// </summary> /// <param name="name">The package name to look for.</param> /// <param name="version">The package version to look for or null to match any version.</param> /// <returns>True if the package exists in NetFrameworkPackages with a version equal to or higher the version specified. Otherwise, false.</returns> private bool ContainsPackageReference(IEnumerable <NuGetReference> packages, string name, string?version) { var reference = packages.FirstOrDefault(r => r.Name.Equals(name, StringComparison.OrdinalIgnoreCase)); // If no packages matched, return false if (reference is null) { return(false); } // If the version isn't specified, then matching the name is sufficient if (version is null || reference.HasWildcardVersion) { return(true); } return(_comparer.Compare(version, reference.Version) <= 0); }
public async Task AnalyzeAsync(IProject project, IDependencyAnalysisState state, CancellationToken token) { if (project is null) { throw new ArgumentNullException(nameof(project)); } if (state is null) { throw new ArgumentNullException(nameof(state)); } var allPackages = new HashSet <NuGetReference>(state.Packages.Concat(project.PackageReferences)); var closure = await _transitiveChecker.GetTransitiveDependenciesAsync(allPackages, state.TargetFrameworks, token).ConfigureAwait(false); var dependencyLookup = allPackages .SelectMany(p => closure.GetDependencies(p)) .ToLookup(p => p.Name); var toRemove = state.Packages .Where(p => { // Temporary fix for packages to exclude from the removal list // Until we have a fix for https://github.com/dotnet/upgrade-assistant/issues/1069 if (p.Name == "Microsoft.WindowsAppSDK") { return(false); } // Only remove a package iff it is transitively brought in with a higher or equal version var versions = dependencyLookup[p.Name].Select(static d => d.Version); if (_comparer.TryFindBestVersion(versions, out var best)) { return(_comparer.Compare(p.Version, best) <= 0); } return(false); })
public int Compare(ResolverPackage x, ResolverPackage y) { if (Object.ReferenceEquals(x, y)) { return(0); } Debug.Assert(string.Equals(x.Id, y.Id, StringComparison.OrdinalIgnoreCase)); // The absent package comes first in the sort order var isXAbsent = x.Absent; var isYAbsent = y.Absent; if (isXAbsent && !isYAbsent) { return(-1); } if (!isXAbsent && isYAbsent) { return(1); } if (isXAbsent && isYAbsent) { return(0); } if (_preferredVersions != null) { //Already installed packages come next in the sort order. var xInstalled = _preferredVersions.Contains(x, _identityComparer); var yInstalled = _preferredVersions.Contains(y, _identityComparer); if (xInstalled && !yInstalled) { return(-1); } if (!xInstalled && yInstalled) { return(1); } } //Prefer listed packages over unlisted if (x.Listed && !y.Listed) { return(-1); } if (!x.Listed && y.Listed) { return(1); } var xv = x.Version; var yv = y.Version; var packageBehavior = _dependencyBehavior; // for new packages use the highest version if (_targetIds.Contains(x.Id, StringComparer.OrdinalIgnoreCase)) { packageBehavior = DependencyBehavior.Highest; } // stay as close to the installed version as possible // Choose upgrades over downgrades // For downgrades choose the highest version // // Example: // 1.0.0 // 1.1.0 // 2.0.0 - installed // 2.1.0 // 3.0.0 // Order: 2.0.0, 2.1.0, 3.0.0, 1.1.0, 1.0.0 if (packageBehavior != DependencyBehavior.Highest && packageBehavior != DependencyBehavior.Ignore) { NuGetVersion installedVersion = null; if (_installedVersions.TryGetValue(x.Id, out installedVersion)) { var xvDowngrade = _versionComparer.Compare(xv, installedVersion) < 0; var yvDowngrade = _versionComparer.Compare(yv, installedVersion) < 0; // the upgrade is preferred over the downgrade if (xvDowngrade && !yvDowngrade) { return(1); } else if (!xvDowngrade && yvDowngrade) { return(-1); } else if (xvDowngrade && yvDowngrade) { // when both are downgrades prefer the highest return(-1 * _versionComparer.Compare(xv, yv)); } } } // Normal switch (packageBehavior) { case DependencyBehavior.Lowest: { return(_versionComparer.Compare(xv, yv)); } case DependencyBehavior.Ignore: case DependencyBehavior.Highest: return(-1 * _versionComparer.Compare(xv, yv)); case DependencyBehavior.HighestMinor: { if (_versionComparer.Equals(xv, yv)) { return(0); } // Take the lowest Major, then the Highest Minor and Patch return(new[] { x, y }.OrderBy(p => p.Version.Major) .ThenByDescending(p => p.Version.Minor) .ThenByDescending(p => p.Version.Patch).FirstOrDefault() == x ? -1 : 1); } case DependencyBehavior.HighestPatch: { if (_versionComparer.Equals(xv, yv)) { return(0); } // Take the lowest Major and Minor, then the Highest Patch return(new[] { x, y }.OrderBy(p => p.Version.Major) .ThenBy(p => p.Version.Minor) .ThenByDescending(p => p.Version.Patch).FirstOrDefault() == x ? -1 : 1); } default: return(_versionComparer.Compare(xv, yv)); } }
/// <summary> /// Returns the smallest range that includes all given ranges. /// </summary> public static VersionRange Combine(IEnumerable<VersionRange> ranges, IVersionComparer comparer) { if (ranges == null) { throw new ArgumentNullException(nameof(ranges)); } if (comparer == null) { throw new ArgumentNullException(nameof(comparer)); } // Default to None for empty lists var result = None; // Remove zero width ranges. Ex: (1.0.0, 1.0.0) // This includes VersionRange.None and any other ranges that satisfy zero versions ranges = ranges.Where(range => HasValidRange(range)); if (ranges.Any()) { var rangeComparer = new VersionRangeComparer(comparer); // start with the first range in the list var first = ranges.First(); var lowest = first.MinVersion; var highest = first.MaxVersion; var includePre = first.IncludePrerelease; // To keep things consistent set min/max inclusive to false when there is no boundary // It is possible to denote an inclusive range with no bounds, but it has no useful meaning for combine var includeLowest = first.IsMinInclusive && first.HasLowerBound; var includeHighest = first.IsMaxInclusive && first.HasUpperBound; // expand the range to inclue all other ranges foreach (var range in ranges.Skip(1)) { // allow prerelease versions in the range if any range allows them includePre |= range.IncludePrerelease; // once we have an unbounded lower we can stop checking if (lowest != null) { if (range.HasLowerBound) { var lowerCompare = comparer.Compare(range.MinVersion, lowest); if (lowerCompare < 0) { // A new lowest was found lowest = range.MinVersion; includeLowest = range.IsMinInclusive; } else if (lowerCompare == 0) { // The lower ends are identical, update the inclusiveness includeLowest |= range.IsMinInclusive; } // lowerCompare > 0 falls into the current range, this is a no-op } else { // No lower bound lowest = null; includeLowest = false; } } // null is the highest we can get, stop checking once it is hit if (highest != null) { if (range.HasUpperBound) { var higherCompare = comparer.Compare(range.MaxVersion, highest); if (higherCompare > 0) { // A new highest was found highest = range.MaxVersion; includeHighest = range.IsMaxInclusive; } else if (higherCompare == 0) { // The higher ends are identical, update the inclusiveness includeHighest |= range.IsMaxInclusive; } // higherCompare < 0 falls into the current range, this is a no-op } else { // No higher bound highest = null; includeHighest = false; } } } // Create the new range using the maximums found result = new VersionRange(lowest, includeLowest, highest, includeHighest, includePre); } return result; }
/// <summary> /// Returns the smallest range that includes all given ranges. /// </summary> public static VersionRange Combine(IEnumerable <VersionRange> ranges, IVersionComparer comparer) { if (ranges == null) { throw new ArgumentNullException(nameof(ranges)); } if (comparer == null) { throw new ArgumentNullException(nameof(comparer)); } // Default to None for empty lists var result = None; // Remove zero width ranges. Ex: (1.0.0, 1.0.0) // This includes VersionRange.None and any other ranges that satisfy zero versions ranges = ranges.Where(range => HasValidRange(range)); if (ranges.Any()) { var rangeComparer = new VersionRangeComparer(comparer); // start with the first range in the list var first = ranges.First(); var lowest = first.MinVersion; var highest = first.MaxVersion; // To keep things consistent set min/max inclusive to false when there is no boundary // It is possible to denote an inclusive range with no bounds, but it has no useful meaning for combine var includeLowest = first.IsMinInclusive && first.HasLowerBound; var includeHighest = first.IsMaxInclusive && first.HasUpperBound; // expand the range to inclue all other ranges foreach (var range in ranges.Skip(1)) { // once we have an unbounded lower we can stop checking if (lowest != null) { if (range.HasLowerBound) { var lowerCompare = comparer.Compare(range.MinVersion, lowest); if (lowerCompare < 0) { // A new lowest was found lowest = range.MinVersion; includeLowest = range.IsMinInclusive; } else if (lowerCompare == 0) { // The lower ends are identical, update the inclusiveness includeLowest |= range.IsMinInclusive; } // lowerCompare > 0 falls into the current range, this is a no-op } else { // No lower bound lowest = null; includeLowest = false; } } // null is the highest we can get, stop checking once it is hit if (highest != null) { if (range.HasUpperBound) { var higherCompare = comparer.Compare(range.MaxVersion, highest); if (higherCompare > 0) { // A new highest was found highest = range.MaxVersion; includeHighest = range.IsMaxInclusive; } else if (higherCompare == 0) { // The higher ends are identical, update the inclusiveness includeHighest |= range.IsMaxInclusive; } // higherCompare < 0 falls into the current range, this is a no-op } else { // No higher bound highest = null; includeHighest = false; } } } // Create the new range using the maximums found result = new VersionRange(lowest, includeLowest, highest, includeHighest); } return(result); }
/// <summary> /// Returns the smallest range that includes all given ranges. /// </summary> public static VersionRange Combine(IEnumerable<VersionRange> ranges, IVersionComparer comparer) { VersionRange result = VersionRange.None; if (ranges.Any()) { VersionRangeComparer rangeComparer = new VersionRangeComparer(comparer); // remove zero ranges ranges = ranges.Where(r => !rangeComparer.Equals(r, VersionRange.None)); var first = ranges.First(); NuGetVersion lowest = first.MinVersion; bool includeLowest = first.IsMinInclusive; NuGetVersion highest = first.MaxVersion; bool includeHighest = first.IsMaxInclusive; bool includePre = first.IncludePrerelease; foreach (var range in ranges.Skip(1)) { includePre |= range.IncludePrerelease; if (!range.HasLowerBound) { lowest = null; includeLowest |= range.IsMinInclusive; } else if (comparer.Compare(range.MinVersion, lowest) < 0) { lowest = range.MinVersion; includeLowest = range.IsMinInclusive; } if (!range.HasUpperBound) { highest = null; includeHighest |= range.IsMinInclusive; } else if (comparer.Compare(range.MinVersion, highest) > 0) { highest = range.MinVersion; includeHighest = range.IsMinInclusive; } } result = new VersionRange(lowest, includeLowest, highest, includeHighest, includePre); } return result; }
/// <summary> /// Determines if an NuGetVersion meets the requirements using the version comparer. /// </summary> /// <param name="version">SemVer to compare.</param> /// <param name="comparer">Version comparer used to determine if the version criteria is met.</param> /// <returns>True if the given version meets the version requirements.</returns> public bool Satisfies(SimpleVersion version, IVersionComparer comparer) { if (version == null) { throw new ArgumentNullException("version"); } // Determine if version is in the given range using the comparer. bool condition = true; if (HasLowerBound) { if (IsMinInclusive) { condition &= comparer.Compare(MinVersion, version) <= 0; } else { condition &= comparer.Compare(MinVersion, version) < 0; } } if (HasUpperBound) { if (IsMaxInclusive) { condition &= comparer.Compare(MaxVersion, version) >= 0; } else { condition &= comparer.Compare(MaxVersion, version) > 0; } } if (!IncludePrerelease) { condition &= IsPrerelease(version) != true; } return condition; }