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);
}
}