Improve performance of installing packages with dependencies for nugetprovider and find-package

This commit is contained in:
Quoc Truong
2016-07-18 14:14:59 -07:00
parent ccd4ca1052
commit e3015e5acf
2 changed files with 42 additions and 14 deletions
@@ -480,7 +480,7 @@
HashSet<PackageItem> temporarilyMarked = new HashSet<PackageItem>(new PackageItemComparer());
// checks that there are no dependency loop
hasDependencyLoop = !DepthFirstVisit(packageItem, temporarilyMarked, permanentlyMarked, dependencyToBeInstalled, request);
hasDependencyLoop = !DepthFirstVisit(packageItem, temporarilyMarked, permanentlyMarked, dependencyToBeInstalled, new HashSet<string>(), request);
if (!hasDependencyLoop)
{
@@ -502,9 +502,10 @@
/// <param name="dependencyToBeInstalled"></param>
/// <param name="permanentlyMarked"></param>
/// <param name="temporarilyMarked"></param>
/// <param name="dependenciesProcessed"></param>
/// <param name="request"></param>
/// <returns></returns>
internal static bool DepthFirstVisit(PackageItem packageItem, HashSet<PackageItem> temporarilyMarked, HashSet<PackageItem> permanentlyMarked, List<PackageItem> dependencyToBeInstalled, NuGetRequest request)
internal static bool DepthFirstVisit(PackageItem packageItem, HashSet<PackageItem> temporarilyMarked, HashSet<PackageItem> permanentlyMarked, List<PackageItem> dependencyToBeInstalled, HashSet<string> dependenciesProcessed, NuGetRequest request)
{
// dependency loop detected because the element is temporarily marked
if (temporarilyMarked.Contains(packageItem))
@@ -523,9 +524,9 @@
temporarilyMarked.Add(packageItem);
// Visit the dependency
foreach (var dependency in GetPackageDependenciesHelper(packageItem, request))
foreach (var dependency in GetPackageDependenciesHelper(packageItem, dependenciesProcessed, request))
{
if (!DepthFirstVisit(dependency, temporarilyMarked, permanentlyMarked, dependencyToBeInstalled, request))
if (!DepthFirstVisit(dependency, temporarilyMarked, permanentlyMarked, dependencyToBeInstalled, dependenciesProcessed, request))
{
// if dfs returns false then we have encountered a loop
return false;
@@ -549,8 +550,9 @@
/// Returns the package dependencies of packageItem. We only return the dependencies that are not installed in the destination folder of request
/// </summary>
/// <param name="packageItem"></param>
/// <param name="depedenciesToProcessed"></param>
/// <param name="request"></param>
private static IEnumerable<PackageItem> GetPackageDependenciesHelper(PackageItem packageItem, NuGetRequest request)
private static IEnumerable<PackageItem> GetPackageDependenciesHelper(PackageItem packageItem, HashSet<string> depedenciesToProcessed, NuGetRequest request)
{
if (packageItem.Package.DependencySetList == null)
{
@@ -567,6 +569,13 @@
foreach (var dep in depSet.Dependencies)
{
var depKey = string.Format(CultureInfo.InvariantCulture, "{0}!#!{1}", dep.Id, dep.DependencyVersion.ToStringSafe());
if (depedenciesToProcessed.Contains(depKey))
{
continue;
}
// Get the min dependencies version
string minVersion = dep.DependencyVersion.MinVersion.ToStringSafe();
@@ -617,6 +626,8 @@
if (installed)
{
// already processed this so don't need to do this next time
depedenciesToProcessed.Add(dep.Id);
request.Verbose(String.Format(CultureInfo.CurrentCulture, Messages.AlreadyInstalled, dep.Id));
// already have a dependency so move on
continue;
@@ -634,7 +645,9 @@
}
// Get the package that is the latest version
yield return dependentPackageItem.OrderByDescending(each => each.Version).FirstOrDefault();
yield return dependentPackageItem.OrderByDescending(each => each.Version).FirstOrDefault();
depedenciesToProcessed.Add(depKey);
}
}
}
@@ -57,7 +57,12 @@ namespace Microsoft.PowerShell.PackageManagement.Cmdlets {
return true;
}
protected override void ProcessPackage(PackageProvider provider, IEnumerable<string> searchKey, SoftwareIdentity package) {
protected override void ProcessPackage(PackageProvider provider, IEnumerable<string> searchKey, SoftwareIdentity package)
{
ProcessPackage(provider, searchKey, package, IncludeDependencies ? new HashSet<string>() : null);
}
private void ProcessPackage(PackageProvider provider, IEnumerable<string> searchKey, SoftwareIdentity package, HashSet<string> processedDependencies) {
try {
@@ -71,14 +76,24 @@ namespace Microsoft.PowerShell.PackageManagement.Cmdlets {
foreach (var dep in package.Dependencies) {
// note: future work may be needed if the package sources currently selected by the user don't
// contain the dependencies.
var dependendcies = PackageManagementService.FindPackageByCanonicalId(dep, this);
var depPkg = dependendcies.OrderByDescending(pp => pp, SoftwareIdentityVersionComparer.Instance).FirstOrDefault();
if (depPkg == null) {
missingDependencies.Add(dep);
Warning(Constants.Messages.UnableToFindDependencyPackage, dep);
} else {
ProcessPackage(depPkg.Provider, searchKey.Select(each => each + depPkg.Name).ToArray(), depPkg);
// this dep is not processed yet
if (!processedDependencies.Contains(dep))
{
var dependendcies = PackageManagementService.FindPackageByCanonicalId(dep, this);
var depPkg = dependendcies.OrderByDescending(pp => pp, SoftwareIdentityVersionComparer.Instance).FirstOrDefault();
processedDependencies.Add(dep);
if (depPkg == null)
{
missingDependencies.Add(dep);
Warning(Constants.Messages.UnableToFindDependencyPackage, dep);
}
else
{
ProcessPackage(depPkg.Provider, searchKey.Select(each => each + depPkg.Name).ToArray(), depPkg, processedDependencies);
}
}
}
if (missingDependencies.Any()) {