Example #1
0
        public void Resolver_Basic_AllUnlisted()
        {
            var a100 = new ResolverPackage("a", new NuGetVersion(1, 0, 0),
                                           new NuGet.Packaging.Core.PackageDependency[]
            {
                new NuGet.Packaging.Core.PackageDependency("b",
                                                           new VersionRange(new NuGetVersion(1, 0, 0), true, new NuGetVersion(5, 0, 0), true))
            },
                                           false,
                                           false);

            var b200 = new ResolverPackage("b", new NuGetVersion(2, 0, 0), null, false, false);
            var b250 = new ResolverPackage("b", new NuGetVersion(2, 5, 0), null, false, false);
            var b400 = new ResolverPackage("b", new NuGetVersion(4, 0, 0), null, false, false);
            var b500 = new ResolverPackage("b", new NuGetVersion(5, 0, 0), null, false, false);
            var b600 = new ResolverPackage("b", new NuGetVersion(6, 0, 0), null, false, false);

            List <ResolverPackage> available = new List <ResolverPackage>();

            available.Add(a100);
            available.Add(b200);
            available.Add(b250);
            available.Add(b400);
            available.Add(b500);
            available.Add(b600);

            var resolver = new PackageResolver();
            var context  = CreatePackageResolverContext(DependencyBehavior.Lowest, a100, available);
            var solution = resolver.Resolve(context, CancellationToken.None)
                           .OrderBy(pi => pi.Id)
                           .ToList();

            Assert.Equal(new PackageIdentity("a", new NuGetVersion(1, 0, 0)), solution[0], PackageIdentityComparer.Default);
            Assert.Equal(new PackageIdentity("b", new NuGetVersion(2, 0, 0)), solution[1], PackageIdentityComparer.Default);
        }
Example #2
0
        public void Resolver_Basic()
        {
            ResolverPackage target = new ResolverPackage("a", new NuGetVersion(1, 0, 0),
                                                         new NuGet.Packaging.Core.PackageDependency[]
            {
                new NuGet.Packaging.Core.PackageDependency("b", new VersionRange(new NuGetVersion(1, 0, 0), true, new NuGetVersion(3, 0, 0), true))
            },
                                                         true,
                                                         false);

            var dep1 = new ResolverPackage("b", new NuGetVersion(2, 0, 0));
            var dep2 = new ResolverPackage("b", new NuGetVersion(2, 5, 0));
            var dep3 = new ResolverPackage("b", new NuGetVersion(4, 0, 0));

            List <ResolverPackage> possible = new List <ResolverPackage>();

            possible.Add(dep1);
            possible.Add(dep2);
            possible.Add(dep3);
            possible.Add(target);

            var resolver = new PackageResolver();
            var context  = CreatePackageResolverContext(DependencyBehavior.Lowest, target, possible);
            var solution = resolver.Resolve(context, CancellationToken.None).ToList();

            Assert.Equal(2, solution.Count());
        }
Example #3
0
        /// <summary>
        /// Ex: PackageA (> 1.0.0)
        /// </summary>
        private static string FormatDependencyConstraint(ResolverPackage package, string dependencyId)
        {
            // The range may not exist, or may inclue all versions. For this reason we trim the string afterwards to remove extra spaces due to empty ranges
            var range            = package.FindDependencyRange(dependencyId);
            var dependencyString = String.Format(CultureInfo.InvariantCulture, "{0} {1}", dependencyId,
                                                 range == null ? string.Empty : range.ToNonSnapshotRange().PrettyPrint()).Trim();

            // A 1.0.0 dependency: B (= 1.5)
            return($"'{package.Id} {package.Version.ToNormalizedString()} constraint: {dependencyString}'");
        }
Example #4
0
        public void Resolver_NoSolution()
        {
            ResolverPackage target = new ResolverPackage("a", new NuGetVersion(1, 0, 0), new NuGet.Packaging.Core.PackageDependency[] { new NuGet.Packaging.Core.PackageDependency("b", null) });

            List <ResolverPackage> possible = new List <ResolverPackage>();

            possible.Add(target);

            var resolver = new PackageResolver(DependencyBehavior.Lowest);

            Assert.Throws <NuGetResolverConstraintException>(() => resolver.Resolve(new ResolverPackage[] { target }, possible, CancellationToken.None));
        }
Example #5
0
        private static IEnumerable <PackageDependency> GetBrokenDependencies(ResolverPackage package, IEnumerable <ResolverPackage> packages)
        {
            foreach (var dependency in package.Dependencies)
            {
                var target = packages.FirstOrDefault(targetPackage => StringComparer.OrdinalIgnoreCase.Equals(targetPackage.Id, dependency.Id));

                if (!IsDependencySatisfied(dependency, target))
                {
                    yield return(dependency);
                }
            }

            yield break;
        }
Example #6
0
        private static List <ResolverPackage> FindCircularDependency(ResolverPackage package, Dictionary <string, ResolverPackage> packageLookUp, HashSet <ResolverPackage> visitedPackages)
        {
            // avoid checking depths beyond 20 packages deep
            if (package != null && !package.Absent && package.Dependencies.Any())
            {
                var queue = new Queue <QueueNode>();

                // added the first initial node to queue
                var node = new QueueNode(package, new List <ResolverPackage>());
                queue.Enqueue(node);

                // BFS traversal to traverse through all the packages to find out circular dependency
                while (queue.Count > 0)
                {
                    var source = queue.Dequeue();

                    // access parent packages list and add current package as well
                    var parentPackages = new List <ResolverPackage>(source.ParentPackages);
                    parentPackages.Add(source.Package);

                    // walk the dependencies
                    foreach (var dependency in source.Package.Dependencies.OrderBy(d => d.Id, StringComparer.OrdinalIgnoreCase))
                    {
                        var dependencyPackage = packageLookUp[dependency.Id];

                        // If already visited, then it means it doesn't have any circular dependency so we can avoid processing this node again
                        if (!visitedPackages.Contains(dependencyPackage))
                        {
                            if (parentPackages.Contains(dependencyPackage))
                            {
                                // circular dependency detected
                                parentPackages.Add(dependencyPackage);
                                return(parentPackages);
                            }
                            // add child node to Queue to process further
                            var newQNode = new QueueNode(dependencyPackage, parentPackages);
                            queue.Enqueue(newQNode);
                        }
                    }
                }
            }

            // add processed packages to local cache
            visitedPackages.Add(package);

            // end of the walk
            return(new List <ResolverPackage>());
        }
Example #7
0
        /// <summary>
        /// Check if two packages can exist in the same solution.
        /// This is used by the resolver.
        /// </summary>
        internal static bool ShouldRejectPackagePair(ResolverPackage p1, ResolverPackage p2)
        {
            var p1ToP2Dependency = p1.FindDependencyRange(p2.Id);

            if (p1ToP2Dependency != null)
            {
                return(p2.Absent || !p1ToP2Dependency.Satisfies(p2.Version));
            }

            var p2ToP1Dependency = p2.FindDependencyRange(p1.Id);

            if (p2ToP1Dependency != null)
            {
                return(p1.Absent || !p2ToP1Dependency.Satisfies(p1.Version));
            }

            return(false);
        }
Example #8
0
        public void Resolver_Basic_AllUnlisted()
        {
            var a100 = new ResolverPackage("a", new NuGetVersion(1, 0, 0),
                new NuGet.Packaging.Core.PackageDependency[]
                    {
                        new NuGet.Packaging.Core.PackageDependency("b",
                            new VersionRange(new NuGetVersion(1, 0, 0), true, new NuGetVersion(5, 0, 0), true))
                    },
                false,
                false);

            var b200 = new ResolverPackage("b", new NuGetVersion(2, 0, 0), null, false, false);
            var b250 = new ResolverPackage("b", new NuGetVersion(2, 5, 0), null, false, false);
            var b400 = new ResolverPackage("b", new NuGetVersion(4, 0, 0), null, false, false);
            var b500 = new ResolverPackage("b", new NuGetVersion(5, 0, 0), null, false, false);
            var b600 = new ResolverPackage("b", new NuGetVersion(6, 0, 0), null, false, false);

            List<ResolverPackage> available = new List<ResolverPackage>();
            available.Add(a100);
            available.Add(b200);
            available.Add(b250);
            available.Add(b400);
            available.Add(b500);
            available.Add(b600);

            var resolver = new PackageResolver();
            var context = CreatePackageResolverContext(DependencyBehavior.Lowest, a100, available);
            var solution = resolver.Resolve(context, CancellationToken.None)
                .OrderBy(pi => pi.Id)
                .ToList();

            Assert.Equal(new PackageIdentity("a", new NuGetVersion(1, 0, 0)), solution[0], PackageIdentityComparer.Default);
            Assert.Equal(new PackageIdentity("b", new NuGetVersion(2, 0, 0)), solution[1], PackageIdentityComparer.Default);
        }
Example #9
0
        private static IEnumerable<ResolverPackage> FindCircularDependency(ResolverPackage package, IEnumerable<string> parents, IEnumerable<ResolverPackage> solution)
        {
            // avoid checking depths beyond 20 packages deep
            if (parents.Count() < 20 && package != null && !package.Absent && package.Dependencies.Any())
            {
                // walk the dependencies
                foreach (var dependency in package.Dependencies.OrderBy(d => d.Id, StringComparer.OrdinalIgnoreCase))
                {
                    var dependencyPackage = solution.FirstOrDefault(solutionPackage => StringComparer.OrdinalIgnoreCase.Equals(solutionPackage.Id, dependency.Id));

                    if (parents.Contains(dependency.Id, StringComparer.OrdinalIgnoreCase))
                    {
                        // loop detected
                        return new ResolverPackage[] { package, dependencyPackage };
                    }

                    // recurse on dependencies
                    var result = FindCircularDependency(dependencyPackage, parents.Concat(new string[] { package.Id }), solution);

                    if (result.Any())
                    {
                        return (new ResolverPackage[] { package }).Concat(result);
                    }
                }
            }

            // end of the walk
            return Enumerable.Empty<ResolverPackage>();
        }
Example #10
0
        /// <summary>
        /// Check if two packages can exist in the same solution.
        /// This is used by the resolver.
        /// </summary>
        internal static bool ShouldRejectPackagePair(ResolverPackage p1, ResolverPackage p2)
        {
            var p1ToP2Dependency = p1.FindDependencyRange(p2.Id);
            if (p1ToP2Dependency != null)
            {
                return p2.Absent || !p1ToP2Dependency.Satisfies(p2.Version);
            }

            var p2ToP1Dependency = p2.FindDependencyRange(p1.Id);
            if (p2ToP1Dependency != null)
            {
                return p1.Absent || !p2ToP1Dependency.Satisfies(p1.Version);
            }

            return false;
        }
Example #11
0
 private static bool IsDependencySatisfied(PackageDependency dependency, ResolverPackage package)
 {
     return package != null && !package.Absent
         && (dependency.VersionRange == null || dependency.VersionRange.Satisfies(package.Version));
 }
Example #12
0
        private static IEnumerable<PackageDependency> GetBrokenDependencies(ResolverPackage package, IEnumerable<ResolverPackage> packages)
        {
            foreach (var dependency in package.Dependencies)
            {
                var target = packages.FirstOrDefault(targetPackage => StringComparer.OrdinalIgnoreCase.Equals(targetPackage.Id, dependency.Id));

                if (!IsDependencySatisfied(dependency, target))
                {
                    yield return dependency;
                }
            }

            yield break;
        }
Example #13
0
        /// <summary>
        /// Ex: PackageA (> 1.0.0)
        /// </summary>
        private static string FormatDependencyConstraint(ResolverPackage package, string dependencyId)
        {
            // The range may not exist, or may inclue all versions. For this reason we trim the string afterwards to remove extra spaces due to empty ranges
            var range = package.FindDependencyRange(dependencyId);
            var dependencyString = String.Format(CultureInfo.InvariantCulture, "{0} {1}", dependencyId,
                range == null ? string.Empty : range.PrettyPrint()).Trim();

            // A 1.0.0 dependency: B (= 1.5)
            return $"'{package.Id} {package.Version.ToString()} {Strings.DependencyConstraint}: {dependencyString}'";
        }
Example #14
0
        /// <summary>
        /// This will try and get broken dependencies for target or it's dependencies WRT installed packages as well as all available packages to install
        /// </summary>
        /// <param name="package">target package</param>
        /// <param name="solution">last best known solution</param>
        /// <param name="availablePackages">all available packages from all sources</param>
        /// <returns>list of broken dependencies</returns>
        private static IEnumerable <PackageDependency> GetBrokenDependenciesWithInstalledPackages(ResolverPackage package, IEnumerable <ResolverPackage> solution, IEnumerable <PackageDependencyInfo> availablePackages, HashSet <string> visitedPackages)
        {
            if (visitedPackages.Contains(package.Id))
            {
                yield break;
            }

            // BFS traversal of graph
            var queue = new Queue <ResolverPackage>();

            queue.Enqueue(package);

            while (queue.Count > 0)
            {
                var node = queue.Dequeue();
                foreach (var dependency in node.Dependencies)
                {
                    var target = solution.FirstOrDefault(targetPackage => StringComparer.OrdinalIgnoreCase.Equals(targetPackage.Id, dependency.Id));

                    // true, if solution doesn't contain this dependency or
                    // if neither solution package satisfy this dependency version nor available packages had any package which could satisfy this dependency.
                    // This is required because our solution might not have selected the right version of this dependent package.
                    if (target == null || (!IsDependencySatisfied(dependency, target) &&
                                           !availablePackages.Where(p => StringComparer.OrdinalIgnoreCase.Equals(p.Id, dependency.Id)).Any(p => IsDependencySatisfied(dependency, p))))
                    {
                        yield return(dependency);
                    }

                    if (target != null && visitedPackages.Add(dependency.Id))
                    {
                        queue.Enqueue(target);
                    }
                }
            }

            yield break;
        }
Example #15
0
        public void Resolver_NoSolution()
        {
            ResolverPackage target = new ResolverPackage("a", new NuGetVersion(1, 0, 0), new NuGet.Packaging.Core.PackageDependency[] { new NuGet.Packaging.Core.PackageDependency("b", null) }, true, false);

            List<ResolverPackage> possible = new List<ResolverPackage>();
            possible.Add(target);

            var resolver = new PackageResolver();
            var context = CreatePackageResolverContext(DependencyBehavior.Lowest, target, possible);

            Assert.Throws<NuGetResolverConstraintException>(() => resolver.Resolve(context, CancellationToken.None));
        }
Example #16
0
        public void Resolver_Basic()
        {
            ResolverPackage target = new ResolverPackage("a", new NuGetVersion(1, 0, 0),
                new NuGet.Packaging.Core.PackageDependency[]
                    {
                        new NuGet.Packaging.Core.PackageDependency("b", new VersionRange(new NuGetVersion(1, 0, 0), true, new NuGetVersion(3, 0, 0), true))
                    },
                true,
                false);

            var dep1 = new ResolverPackage("b", new NuGetVersion(2, 0, 0));
            var dep2 = new ResolverPackage("b", new NuGetVersion(2, 5, 0));
            var dep3 = new ResolverPackage("b", new NuGetVersion(4, 0, 0));

            List<ResolverPackage> possible = new List<ResolverPackage>();
            possible.Add(dep1);
            possible.Add(dep2);
            possible.Add(dep3);
            possible.Add(target);

            var resolver = new PackageResolver();
            var context = CreatePackageResolverContext(DependencyBehavior.Lowest, target, possible);
            var solution = resolver.Resolve(context, CancellationToken.None).ToList();

            Assert.Equal(2, solution.Count());
        }
Example #17
0
 public QueueNode(ResolverPackage package, List <ResolverPackage> parentPackages)
 {
     Package        = package;
     ParentPackages = parentPackages;
 }
Example #18
0
 private static bool IsDependencySatisfied(PackageDependency dependency, ResolverPackage package)
 {
     return(package != null && !package.Absent &&
            (dependency.VersionRange == null || dependency.VersionRange.Satisfies(package.Version)));
 }