/// <summary> /// Generates an installation plan /// </summary> /// <param name="productPackages">Current product</param> /// <param name="packages">Packages to install</param> /// <returns><see cref="InstallationPlan" /></returns> public async Task <InstallationPlan> PlanInstallation(IPackageGraph productPackages, ICollection <PackageId> packages) { var plan = new InstallationPlan(); var resolvedPackagesDictionary = new Dictionary <PackageId, DeploymentPackageInfo>(); var resolvedPackages = await NuGetEngine.ResolvePackages(packages); NuGetEngine.AnalyzePackages(resolvedPackages); var graphBuilder = new PackageGraphBuilder(); foreach (var innerNode in resolvedPackages.InnerNodes) { TranslateNuGetGraphNode(innerNode, graphBuilder, resolvedPackagesDictionary); } plan.TargetPackageGraph = graphBuilder.Build(); var resolvedPackagesList = plan.TargetPackageGraph.FlattenMostDependentFirst(); var productPackagesList = productPackages.FlattenMostDependentFirst(); var deploymentActions = new List <DeploymentAction>(); foreach (var packageId in resolvedPackagesList) { var packageMatch = productPackagesList.FirstOrDefault(x => x.Id == packageId.Id); var isUpdate = (packageMatch != null) && (packageMatch.Version != packageId.Version); var install = (packageMatch == null) || isUpdate; if (isUpdate) { deploymentActions.Add(new DeletePackageAction(DeploymentContext, true, packageMatch)); plan.UpdateCount++; } if (install) { var packageInfo = resolvedPackagesDictionary[packageId]; deploymentActions.Add(new DownloadPackageAction(DeploymentContext, isUpdate, packageInfo, NuGetEngine, PackagesFolderPath)); deploymentActions.Add(new InstallPackageAction(DeploymentContext, isUpdate, packageInfo, DeploymentStrategyProvider)); if (!isUpdate) { plan.InstallCount++; } } else { plan.RemainingPackages.Add(packageId); } } plan.Actions = deploymentActions.Where(x => x is DownloadPackageAction) .Concat(deploymentActions.Where(x => x is DeletePackageAction)) .Concat(deploymentActions.Where(x => x is InstallPackageAction)) .ToList(); return(plan); }
public async Task PackageWithDependencyAreResolvedInAdditionToProductPackage() { using (var helper = new TestDeploymentHelper().WithConfiguration().AndNuGetSource()) { var newPackages = new[] { new PackageId("bootstrap", string.Empty, false) }; var productPackages = new PackageGraphBuilder() .Append(new PackageId("Newtonsoft.Json", "9.0.1", false), new PackageId[] {}) .Build(); var engine = helper.CreatEngine(); var discoveredPackages = await engine.PackageDiscoverer.Discover(productPackages, newPackages); var plan = await engine.PackageDeployer.PlanInstallation(productPackages, discoveredPackages); plan.InstallCount.Should().Be(2); var packages = plan.TargetPackageGraph.FlattenLeastDependentFirst(); packages.FirstOrDefault(x => x.IsSamePackage(new PackageId("bootstrap/3.3.7"))).Should().NotBeNull(); packages.FirstOrDefault(x => x.Id == "jQuery").Should().NotBeNull(); } }
public async Task ProductPackageVersionIsDowngraded() { using (var helper = new TestDeploymentHelper().WithConfiguration().AndNuGetSource()) { var newPackages = new[] { new PackageId("bootstrap", "[3.2.0]", false) }; var productPackages = new PackageGraphBuilder() .Append(new PackageId("bootstrap", "3.7.0", false), new PackageId[] { }) .Build(); var engine = helper.CreatEngine(); engine.NuGetEngine.AllowDowngrades = true; var discoveredPackages = await engine.PackageDiscoverer.Discover(productPackages, newPackages); var plan = await engine.PackageDeployer.PlanInstallation(productPackages, discoveredPackages); var packages = plan.TargetPackageGraph.FlattenLeastDependentFirst(); packages.FirstOrDefault(x => x.IsSamePackage(new PackageId("bootstrap/3.2.0"))).Should().NotBeNull(); packages.FirstOrDefault(x => x.Id == "jQuery").Should().NotBeNull(); } }
/// <summary> /// Translates NuGet package graph into <see cref="PackageGraph"/> using <see cref="PackageGraphBuilder"/> /// </summary> /// <param name="node">NuGet package node</param> /// <param name="graphBuilder">The graph builder.</param> /// <param name="resolvedPackagesDictionary">The resolved packages dictionary.</param> /// <returns>PackageId for the translated package</returns> /// <exception cref="System.ArgumentException"></exception> protected PackageId TranslateNuGetGraphNode(GraphNode <RemoteResolveResult> node, PackageGraphBuilder graphBuilder, Dictionary <PackageId, DeploymentPackageInfo> resolvedPackagesDictionary) { if (node.Key.TypeConstraint != LibraryDependencyTarget.Package && node.Key.TypeConstraint != LibraryDependencyTarget.PackageProjectExternal) { throw new ArgumentException($"Package {node.Key.Name} cannot be resolved from the sources"); } var package = new DeploymentPackageInfo { Id = new PackageId(node.Item.Key.Name, node.Item.Key.Version.ToNormalizedString(), node.Item.Key.Version.IsPrerelease), Match = node.Item.Data.Match }; graphBuilder.Append(package.Id, node.InnerNodes.Select(x => TranslateNuGetGraphNode(x, graphBuilder, resolvedPackagesDictionary))); if (!resolvedPackagesDictionary.ContainsKey(package.Id)) { resolvedPackagesDictionary.Add(package.Id, package); } return(package.Id); }