Stores information about a conflict during an install.
Exemple #1
0
        protected override void OnBeforePackageWalk(IPackage package)
        {
            ConflictResult conflict = this.GetConflict(package);

            if ((conflict != null) && !PackageEqualityComparer.IdAndVersion.Equals(package, conflict.Package))
            {
                IEnumerable <IPackage> source = from dependentPackage in this.GetDependents(conflict)
                                                let dependency = dependentPackage.FindDependency(package.Id, this.TargetFramework)
                                                                 where (dependency != null) && !dependency.VersionSpec.Satisfies(package.Version)
                                                                 select dependentPackage;
                if (source.Any <IPackage>() && !this.TryUpdate(source, conflict, package, out source))
                {
                    throw CreatePackageConflictException(package, conflict.Package, source);
                }
                if (this._isDowngrade || (package.Version >= conflict.Package.Version))
                {
                    this.Uninstall(conflict.Package, conflict.DependentsResolver, conflict.Repository);
                }
                else
                {
                    object[] args = new object[] { package.Id };
                    throw new InvalidOperationException(string.Format(CultureInfo.CurrentCulture, NuGetResources.NewerVersionAlreadyReferenced, args));
                }
            }
        }
Exemple #2
0
        private IEnumerable <IPackage> GetDependents(ConflictResult conflict)
        {
            // Skip all dependents that are marked for uninstall
            IEnumerable <IPackage> packages = _operations.GetPackages(PackageAction.Uninstall);

            return(conflict.DependentsResolver.GetDependents(conflict.Package)
                   .Except(packages, PackageEqualityComparer.IdAndVersion));
        }
Exemple #3
0
        protected override ConflictResult GetConflict(IPackage package)
        {
            ConflictResult conflict = base.GetConflict(package);

            if (conflict == null)
            {
                IPackage conflictingPackage = base.Repository.FindPackage(package.Id);
                if (conflictingPackage != null)
                {
                    conflict = new ConflictResult(conflictingPackage, base.Repository, this._dependentsResolver);
                }
            }
            return(conflict);
        }
        protected override ConflictResult GetConflict(IPackage package)
        {
            // For project installs we first try to base behavior (using the live graph)
            // then we look for conflicts for packages installed into the current project.
            ConflictResult result = base.GetConflict(package);

            if (result == null)
            {
                IPackage existingPackage = Repository.FindPackage(package.Id);

                if (existingPackage != null)
                {
                    result = new ConflictResult(existingPackage, Repository, _dependentsResolver);
                }
            }
            return(result);
        }
Exemple #5
0
        protected override ConflictResult GetConflict(IPackage package)
        {
            // For project installs we first try to base behavior (using the live graph)
            // then we look for conflicts for packages installed into the current project.
            ConflictResult result = base.GetConflict(package);

            if (result == null)
            {
                IPackage existingPackage = Repository.FindPackage(package.Id);

                if (existingPackage != null)
                {
                    result = new ConflictResult(existingPackage, Repository, _dependentsResolver);
                }
            }
            return result;
        }
Exemple #6
0
        protected override void OnBeforePackageWalk(IPackage package)
        {
            ConflictResult conflictResult = GetConflict(package);

            if (conflictResult == null)
            {
                return;
            }

            // If the conflicting package is the same as the package being installed
            // then no-op
            if (PackageEqualityComparer.IdAndVersion.Equals(package, conflictResult.Package))
            {
                return;
            }

            // First we get a list of dependents for the installed package.
            // Then we find the dependency in the foreach dependent that this installed package used to satisfy.
            // We then check if the resolved package also meets that dependency and if it doesn't it's added to the list
            // i.e. A1 -> C >= 1
            //      B1 -> C >= 1
            //      C2 -> []
            // Given the above graph, if we upgrade from C1 to C2, we need to see if A and B can work with the new C
            var incompatiblePackages = from dependentPackage in GetDependents(conflictResult)
                                       let dependency = dependentPackage.FindDependency(package.Id, TargetFramework)
                                                        where dependency != null && !dependency.VersionSpec.Satisfies(package.Version)
                                                        select dependentPackage;

            // If there were incompatible packages that we failed to update then we throw an exception
            if (incompatiblePackages.Any() && !TryUpdate(incompatiblePackages, conflictResult, package, out incompatiblePackages))
            {
                throw CreatePackageConflictException(package, conflictResult.Package, incompatiblePackages);
            }
            else if (package.Version < conflictResult.Package.Version)
            {
                // REVIEW: Should we have a flag to allow downgrading?
                throw new InvalidOperationException(
                          String.Format(CultureInfo.CurrentCulture,
                                        NuGetResources.NewerVersionAlreadyReferenced, package.Id));
            }
            else if (package.Version > conflictResult.Package.Version)
            {
                Uninstall(conflictResult.Package, conflictResult.DependentsResolver, conflictResult.Repository);
            }
        }
Exemple #7
0
        private IEnumerable<IPackage> GetDependents(ConflictResult conflict)
        {
            // Skip all dependents that are marked for uninstall
            IEnumerable<IPackage> packages = _operations.GetPackages(PackageAction.Uninstall);

            return conflict.DependentsResolver.GetDependents(conflict.Package)
                                              .Except(packages, PackageEqualityComparer.IdAndVersion);
        }
Exemple #8
0
        private bool TryUpdate(IEnumerable<IPackage> dependents, ConflictResult conflictResult, IPackage package, out IEnumerable<IPackage> incompatiblePackages)
        {
            // Key dependents by id so we can look up the old package later
            var dependentsLookup = dependents.ToDictionary(d => d.Id, StringComparer.OrdinalIgnoreCase);
            var compatiblePackages = new Dictionary<IPackage, IPackage>();

            // Initialize each compatible package to null
            foreach (var dependent in dependents)
            {
                compatiblePackages[dependent] = null;
            }

            // Get compatible packages in one batch so we don't have to make requests for each one
            var packages = from p in SourceRepository.FindCompatiblePackages(ConstraintProvider, dependentsLookup.Keys, package, TargetFramework, AllowPrereleaseVersions)
                           group p by p.Id into g
                           let oldPackage = dependentsLookup[g.Key]
                           select new
                           {
                               OldPackage = oldPackage,
                               NewPackage = g.Where(p => p.Version > oldPackage.Version)
                                             .OrderBy(p => p.Version)
                                             .ResolveSafeVersion()
                           };

            foreach (var p in packages)
            {
                compatiblePackages[p.OldPackage] = p.NewPackage;
            }

            // Get all packages that have an incompatibility with the specified package i.e.
            // We couldn't find a version in the repository that works with the specified package.
            incompatiblePackages = compatiblePackages.Where(p => p.Value == null)
                                                     .Select(p => p.Key);

            if (incompatiblePackages.Any())
            {
                return false;
            }

            IPackageConstraintProvider currentConstraintProvider = ConstraintProvider;

            try
            {
                // Add a constraint for the incoming package so we don't try to update it by mistake.
                // Scenario:
                // A 1.0 -> B [1.0]
                // B 1.0.1, B 1.5, B 2.0
                // A 2.0 -> B (any version)
                // We have A 1.0 and B 1.0 installed. When trying to update to B 1.0.1, we'll end up trying
                // to find a version of A that works with B 1.0.1. The version in the above case is A 2.0.
                // When we go to install A 2.0 we need to make sure that when we resolve it's dependencies that we stay within bounds
                // i.e. when we resolve B for A 2.0 we want to keep the B 1.0.1 we've already chosen instead of trying to grab
                // B 1.5 or B 2.0. In order to achieve this, we add a constraint for version of B 1.0.1 so we stay within those bounds for B.

                // Respect all existing constraints plus an additional one that we specify based on the incoming package
                var constraintProvider = new DefaultConstraintProvider();
                constraintProvider.AddConstraint(package.Id, new VersionSpec(package.Version));
                ConstraintProvider = new AggregateConstraintProvider(ConstraintProvider, constraintProvider);

                // Mark the incoming package as visited so that we don't try walking the graph again
                Marker.MarkVisited(package);

                var failedPackages = new List<IPackage>();
                // Update each of the existing packages to more compatible one
                foreach (var pair in compatiblePackages)
                {
                    try
                    {
                        // Remove the old package
                        Uninstall(pair.Key, conflictResult.DependentsResolver, conflictResult.Repository);

                        // Install the new package
                        Walk(pair.Value);
                    }
                    catch
                    {
                        // If we failed to update this package (most likely because of a conflict further up the dependency chain)
                        // we keep track of it so we can report an error about the top level package.
                        failedPackages.Add(pair.Key);
                    }
                }

                incompatiblePackages = failedPackages;

                return !incompatiblePackages.Any();
            }
            finally
            {
                // Restore the current constraint provider
                ConstraintProvider = currentConstraintProvider;

                // Mark the package as processing again
                Marker.MarkProcessing(package);
            }
        }
Exemple #9
0
        private bool TryUpdate(IEnumerable <IPackage> dependents, ConflictResult conflictResult, IPackage package, out IEnumerable <IPackage> incompatiblePackages)
        {
            // Key dependents by id so we can look up the old package later
            var dependentsLookup   = dependents.ToDictionary(d => d.Id, StringComparer.OrdinalIgnoreCase);
            var compatiblePackages = new Dictionary <IPackage, IPackage>();

            // Initialize each compatible package to null
            foreach (var dependent in dependents)
            {
                compatiblePackages[dependent] = null;
            }

            // Get compatible packages in one batch so we don't have to make requests for each one
            var packages = from p in SourceRepository.FindCompatiblePackages(ConstraintProvider, dependentsLookup.Keys, package, TargetFramework, AllowPrereleaseVersions)
                           group p by p.Id into g
                           let oldPackage = dependentsLookup[g.Key]
                                            select new
            {
                OldPackage = oldPackage,
                NewPackage = g.Where(p => p.Version > oldPackage.Version)
                             .OrderBy(p => p.Version)
                             .ResolveSafeVersion()
            };

            foreach (var p in packages)
            {
                compatiblePackages[p.OldPackage] = p.NewPackage;
            }

            // Get all packages that have an incompatibility with the specified package i.e.
            // We couldn't find a version in the repository that works with the specified package.
            incompatiblePackages = compatiblePackages.Where(p => p.Value == null)
                                   .Select(p => p.Key);

            if (incompatiblePackages.Any())
            {
                return(false);
            }

            IPackageConstraintProvider currentConstraintProvider = ConstraintProvider;

            try
            {
                // Add a constraint for the incoming package so we don't try to update it by mistake.
                // Scenario:
                // A 1.0 -> B [1.0]
                // B 1.0.1, B 1.5, B 2.0
                // A 2.0 -> B (any version)
                // We have A 1.0 and B 1.0 installed. When trying to update to B 1.0.1, we'll end up trying
                // to find a version of A that works with B 1.0.1. The version in the above case is A 2.0.
                // When we go to install A 2.0 we need to make sure that when we resolve it's dependencies that we stay within bounds
                // i.e. when we resolve B for A 2.0 we want to keep the B 1.0.1 we've already chosen instead of trying to grab
                // B 1.5 or B 2.0. In order to achieve this, we add a constraint for version of B 1.0.1 so we stay within those bounds for B.

                // Respect all existing constraints plus an additional one that we specify based on the incoming package
                var constraintProvider = new DefaultConstraintProvider();
                constraintProvider.AddConstraint(package.Id, new VersionSpec(package.Version));
                ConstraintProvider = new AggregateConstraintProvider(ConstraintProvider, constraintProvider);

                // Mark the incoming package as visited so that we don't try walking the graph again
                Marker.MarkVisited(package);

                var failedPackages = new List <IPackage>();
                // Update each of the existing packages to more compatible one
                foreach (var pair in compatiblePackages)
                {
                    try
                    {
                        // Remove the old package
                        Uninstall(pair.Key, conflictResult.DependentsResolver, conflictResult.Repository);

                        // Install the new package
                        Walk(pair.Value);
                    }
                    catch
                    {
                        // If we failed to update this package (most likely because of a conflict further up the dependency chain)
                        // we keep track of it so we can report an error about the top level package.
                        failedPackages.Add(pair.Key);
                    }
                }

                incompatiblePackages = failedPackages;

                return(!incompatiblePackages.Any());
            }
            finally
            {
                // Restore the current constraint provider
                ConstraintProvider = currentConstraintProvider;

                // Mark the package as processing again
                Marker.MarkProcessing(package);
            }
        }
Exemple #10
0
        private IEnumerable <IPackage> GetDependents(ConflictResult conflict)
        {
            IEnumerable <IPackage> packages = this._operations.GetPackages(PackageAction.Uninstall);

            return(conflict.DependentsResolver.GetDependents(conflict.Package).Except <IPackage>(packages, ((IEqualityComparer <IPackage>)PackageEqualityComparer.IdAndVersion)));
        }
Exemple #11
0
        private bool TryUpdate(IEnumerable <IPackage> dependents, ConflictResult conflictResult, IPackage package, out IEnumerable <IPackage> incompatiblePackages)
        {
            bool flag;
            Dictionary <string, IPackage>   dependentsLookup = Enumerable.ToDictionary <IPackage, string>(dependents, d => d.Id, StringComparer.OrdinalIgnoreCase);
            Dictionary <IPackage, IPackage> dictionary       = new Dictionary <IPackage, IPackage>();

            foreach (IPackage package2 in dependents)
            {
                dictionary[package2] = null;
            }
            foreach (var type in from p in FindCompatiblePackages(this.DependencyResolver, this.ConstraintProvider, dependentsLookup.Keys, package, base.TargetFramework, this.AllowPrereleaseVersions)
                     group p by p.Id into g
                     let oldPackage = dependentsLookup[g.Key]
                                      select new {
                OldPackage = oldPackage,
                NewPackage = this.SelectDependency(from p in g
                                                   where p.Version > oldPackage.Version
                                                   orderby p.Version
                                                   select p)
            })
            {
                dictionary[type.OldPackage] = type.NewPackage;
            }
            incompatiblePackages = from p in dictionary
                                   where p.Value == null
                                   select p.Key;

            if (incompatiblePackages.Any <IPackage>())
            {
                return(false);
            }
            IPackageConstraintProvider constraintProvider = this.ConstraintProvider;

            try
            {
                DefaultConstraintProvider provider2 = new DefaultConstraintProvider();
                provider2.AddConstraint(package.Id, new VersionSpec(package.Version));
                IPackageConstraintProvider[] constraintProviders = new IPackageConstraintProvider[] { this.ConstraintProvider, provider2 };
                this.ConstraintProvider = new AggregateConstraintProvider(constraintProviders);
                base.Marker.MarkVisited(package);
                List <IPackage> list = new List <IPackage>();
                foreach (KeyValuePair <IPackage, IPackage> pair in dictionary)
                {
                    try
                    {
                        this.Uninstall(pair.Key, conflictResult.DependentsResolver, conflictResult.Repository);
                        base.Walk(pair.Value);
                    }
                    catch
                    {
                        list.Add(pair.Key);
                    }
                }
                incompatiblePackages = list;
                flag = !incompatiblePackages.Any <IPackage>();
            }
            finally
            {
                this.ConstraintProvider = constraintProvider;
                base.Marker.MarkProcessing(package);
            }
            return(flag);
        }
Exemple #12
0
        protected override void OnBeforePackageWalk(IPackage package)
        {
            ConflictResult conflictResult = GetConflict(package.Id);

            if (conflictResult == null)
            {
                return;
            }

            // If the conflicting package is the same as the package being installed
            // then no-op
            if (PackageEqualityComparer.IdAndVersion.Equals(package, conflictResult.Package))
            {
                return;
            }

            // First we get a list of dependents for the installed package.
            // Then we find the dependency in the foreach dependent that this installed package used to satisfy.
            // We then check if the resolved package also meets that dependency and if it doesn't it's added to the list
            // i.e A1 -> C >= 1
            //     B1 -> C >= 1
            //     C2 -> []
            // Given the above graph, if we upgrade from C1 to C2, we need to see if A and B can work with the new C
            var dependents = from dependentPackage in GetDependents(conflictResult)
                             where !IsDependencySatisfied(dependentPackage, package)
                             select dependentPackage;

            if (dependents.Any())
            {
                throw CreatePackageConflictException(package, conflictResult.Package, dependents);
            }
            else if (package.Version < conflictResult.Package.Version)
            {
                throw new InvalidOperationException(
                          String.Format(CultureInfo.CurrentCulture,
                                        NuGetResources.NewerVersionAlreadyReferenced, package.Id));
            }
            else if (package.Version > conflictResult.Package.Version)
            {
                // If this package isn't part of the current graph (i.e. hasn't been visited yet) and
                // is marked for removal, then do nothing. This is so we don't get unnecessary duplicates.
                if (!Marker.Contains(conflictResult.Package) &&
                    _operations.Contains(conflictResult.Package, PackageAction.Uninstall))
                {
                    return;
                }

                // Uninstall the conflicting package. We set throw on conflicts to false since we've
                // already decided that there were no conflicts based on the above code.
                var resolver = new UninstallWalker(conflictResult.Repository,
                                                   conflictResult.DependentsResolver,
                                                   NullLogger.Instance,
                                                   removeDependencies: !IgnoreDependencies,
                                                   forceRemove: false)
                {
                    ThrowOnConflicts = false
                };

                foreach (var operation in resolver.ResolveOperations(conflictResult.Package))
                {
                    _operations.AddOperation(operation);
                }
            }
        }