示例#1
0
        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);
        }
示例#3
0
        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]);
        }
示例#4
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 }
            });
        }
示例#6
0
        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);
        }
示例#7
0
        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);
        }
示例#9
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));
            }
        }
示例#11
0
        /// <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;
        }
示例#14
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(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;
        }