예제 #1
0
        public async Task PackagePreFetcher_PackageAlreadyExists()
        {
            using (var sourceDir = TestDirectory.Create())
                using (var packagesFolderDir = TestDirectory.Create())
                    using (var globalPackagesFolder = TestDirectory.Create())
                    {
                        // Arrange
                        var actions        = new List <NuGetProjectAction>();
                        var packagesFolder = new FolderNuGetProject(packagesFolderDir);
                        var testSettings   = NullSettings.Instance;
                        var logger         = new TestLogger();
                        var target         = new PackageIdentity("packageA", NuGetVersion.Parse("1.0.0"));
                        var source         = Repository.Factory.GetVisualStudio(new Configuration.PackageSource(sourceDir.Path));

                        // Add package
                        AddToPackagesFolder(target, packagesFolderDir);
                        actions.Add(NuGetProjectAction.CreateInstallProjectAction(target, source, packagesFolder));

                        AddToSource(target, sourceDir);

                        // Act
                        using (var cacheContext = new SourceCacheContext())
                        {
                            var result = await PackagePreFetcher.GetPackagesAsync(
                                actions,
                                packagesFolder,
                                new PackageDownloadContext(cacheContext),
                                globalPackagesFolder,
                                logger,
                                CancellationToken.None);

                            var downloadResult = await result[target].GetResultAsync();

                            // Assert
                            Assert.Equal(1, result.Count);
                            Assert.True(result[target].InPackagesFolder);
                            Assert.Null(result[target].Source);
                            Assert.Equal(target, result[target].Package);
                            Assert.True(result[target].IsComplete);
                            Assert.Equal(target, downloadResult.PackageReader.GetIdentity());
                            Assert.NotNull(downloadResult.PackageStream);
                            Assert.Equal(DownloadResourceResultStatus.Available, downloadResult.Status);
                        }
                    }
        }
        public async Task EnsurePackageCompatibility_WithValidProjectActions_Succeeds()
        {
            // Arrange
            using (var userPackageFolder = TestDirectory.Create())
            {
                var tc = new TestContext(userPackageFolder);

                await SimpleTestPackageUtility.CreateFolderFeedV3Async(
                    userPackageFolder,
                    PackageSaveMode.Defaultv3,
                    new[]
                {
                    new SimpleTestPackageContext(tc.PackageIdentityA)
                    {
                        PackageTypes = { PackageType.DotnetCliTool }
                    },
                    new SimpleTestPackageContext(tc.PackageIdentityB)     // Not inspected, because this package is
                                                                          // being uninstalled, not installed.
                    {
                        PackageTypes = { tc.InvalidPackageType }
                    },
                    new SimpleTestPackageContext(tc.PackageIdentityC)
                    {
                        PackageTypes = { PackageType.Dependency }
                    },
                });

                // Act & Assert
                tc.Target.EnsurePackageCompatibility(
                    tc.ProjectKProject,
                    tc.NuGetPathContext.Object,
                    new NuGetProjectAction[]
                {
                    NuGetProjectAction.CreateInstallProjectAction(tc.PackageIdentityA, tc.SourceRepository, tc.ProjectKProject),
                    NuGetProjectAction.CreateUninstallProjectAction(tc.PackageIdentityB, tc.ProjectKProject),
                    NuGetProjectAction.CreateInstallProjectAction(tc.PackageIdentityC, tc.SourceRepository, tc.ProjectKProject)
                },
                    tc.GetRestoreResult(new[]
                {
                    tc.PackageIdentityA,
                    tc.PackageIdentityB,
                    tc.PackageIdentityC
                }));
            }
        }
예제 #3
0
        public async Task PackagePreFetcher_PackageDoesNotExistAnywhere()
        {
            using (var sourceDir = TestDirectory.Create())
                using (var packagesFolderDir = TestDirectory.Create())
                    using (var globalPackagesFolder = TestDirectory.Create())
                    {
                        // Arrange
                        var actions        = new List <NuGetProjectAction>();
                        var packagesFolder = new FolderNuGetProject(packagesFolderDir);
                        var testSettings   = new Configuration.NullSettings();
                        var logger         = new TestLogger();
                        var target         = new PackageIdentity("packageA", NuGetVersion.Parse("1.0.0"));
                        var source         = Repository.Factory.GetVisualStudio(new Configuration.PackageSource(sourceDir.Path));

                        actions.Add(NuGetProjectAction.CreateInstallProjectAction(target, source, packagesFolder));

                        // Act
                        using (var cacheContext = new SourceCacheContext())
                        {
                            var result = await PackagePreFetcher.GetPackagesAsync(
                                actions,
                                packagesFolder,
                                new PackageDownloadContext(cacheContext),
                                globalPackagesFolder,
                                logger,
                                CancellationToken.None);

                            Exception exception = null;

                            try
                            {
                                var downloadResult = await result[target].GetResultAsync();
                                Assert.True(false);
                            }
                            catch (Exception ex)
                            {
                                exception = ex;
                            }

                            // Assert
                            Assert.StartsWith("Package 'packageA.1.0.0' is not found on source", exception.Message);
                        }
                    }
        }
예제 #4
0
        public void ProjectActionsExecuted_WhenSolutionManagerActionsExecutedEventRaised_DistinctIdsReturned()
        {
            NuGetUIContext context  = CreateNuGetUIContext();
            var            projectA = new TestNuGetProject();
            var            projectB = new TestNuGetProject();

            var projectActionA1 = NuGetProjectAction.CreateInstallProjectAction(
                PackageIdentity,
                sourceRepository: null,
                projectA);
            var projectActionA2 = NuGetProjectAction.CreateInstallProjectAction(
                PackageIdentity,
                sourceRepository: null,
                projectA);
            var projectActionB = NuGetProjectAction.CreateInstallProjectAction(
                PackageIdentity,
                sourceRepository: null,
                projectB);
            var resolvedActions = new ResolvedAction[]
            {
                new ResolvedAction(projectA, projectActionA1),
                new ResolvedAction(projectA, projectActionA2),
                new ResolvedAction(projectB, projectActionB),
            };
            var wasEventRaised = false;

            string[] expectedProjectIds = resolvedActions
                                          .Select(resolvedAction => resolvedAction.Project.GetMetadata <string>(NuGetProjectMetadataKeys.ProjectId))
                                          .Distinct()
                                          .ToArray();

            context.ProjectActionsExecuted += (object sender, IReadOnlyCollection <string> actualProjectIds) =>
            {
                wasEventRaised = true;

                Assert.Equal(expectedProjectIds, actualProjectIds);
            };

            _solutionManager.Raise(s => s.ActionsExecuted += null, new ActionsExecutedEventArgs(resolvedActions));

            Assert.True(wasEventRaised);
        }
예제 #5
0
        public void ApplyChanges_SortPackages_LastPackage()
        {
            // Arrange
            var lockFile = new PackagesLockFile
            {
                Targets = new List <PackagesLockFileTarget>
                {
                    new PackagesLockFileTarget
                    {
                        Dependencies = new List <LockFileDependency>
                        {
                            new LockFileDependency
                            {
                                Id = "packageB",
                                ResolvedVersion = NuGetVersion.Parse("1.0.0")
                            },
                            new LockFileDependency
                            {
                                Id = "packageD",
                                ResolvedVersion = NuGetVersion.Parse("1.0.0")
                            }
                        }
                    }
                }
            };

            var actionList = new List <NuGetProjectAction>
            {
                NuGetProjectAction.CreateInstallProjectAction(new PackageIdentity("packageE", NuGetVersion.Parse("1.0.0")), null, null)
            };

            var contentHashUtility = new Mock <IPackagesConfigContentHashProvider>();

            // Act
            PackagesConfigLockFileUtility.ApplyChanges(lockFile, actionList, contentHashUtility.Object, CancellationToken.None);

            // Assert
            Assert.Equal(3, lockFile.Targets[0].Dependencies.Count);
            Assert.Equal("packageB", lockFile.Targets[0].Dependencies[0].Id);
            Assert.Equal("packageD", lockFile.Targets[0].Dependencies[1].Id);
            Assert.Equal("packageE", lockFile.Targets[0].Dependencies[2].Id);
        }
예제 #6
0
        public void OnAfterExecuteActions_PackageUninstallAction_PackageUninstalledEventFired()
        {
            CreateNuGetProject();
            var packageIdentity = new PackageIdentity("Test", NuGetVersion.Parse("1.2"));
            var actions         = new List <NuGetProjectAction> ();
            var action          = NuGetProjectAction.CreateUninstallProjectAction(packageIdentity, project);

            actions.Add(action);
            PackageManagementEventArgs eventArgs = null;

            project.PackageManagementEvents.PackageUninstalled += (sender, e) => {
                eventArgs = e;
            };

            project.OnAfterExecuteActions(actions);

            Assert.AreEqual("Test", eventArgs.Id);
            Assert.AreEqual("1.2", eventArgs.Version.ToString());
            Assert.AreEqual(packageIdentity, eventArgs.Package);
        }
예제 #7
0
        public async Task PackagePreFetcher_PackageAlreadyExists_NonNormalizedVersionInput()
        {
            using (var sourceDir = TestFileSystemUtility.CreateRandomTestFolder())
                using (var packagesFolderDir = TestFileSystemUtility.CreateRandomTestFolder())
                {
                    // Arrange
                    var actions             = new List <NuGetProjectAction>();
                    var packagesFolder      = new FolderNuGetProject(packagesFolderDir);
                    var testSettings        = new Configuration.NullSettings();
                    var logger              = new TestLogger();
                    var target              = new PackageIdentity("packageA", NuGetVersion.Parse("1.0.0"));
                    var targetNonNormalized = new PackageIdentity("packageA", NuGetVersion.Parse("1.0"));
                    var source              = Repository.Factory.GetVisualStudio(new Configuration.PackageSource(sourceDir.Path));

                    // Add package
                    AddToPackagesFolder(target, packagesFolderDir);
                    actions.Add(NuGetProjectAction.CreateInstallProjectAction(targetNonNormalized, source));

                    AddToSource(target, sourceDir);

                    // Act
                    var result = await PackagePreFetcher.GetPackagesAsync(
                        actions,
                        packagesFolder,
                        testSettings,
                        logger,
                        CancellationToken.None);

                    var downloadResult = await result[target].GetResultAsync();

                    // Assert
                    Assert.Equal(1, result.Count);
                    Assert.True(result[target].InPackagesFolder);
                    Assert.Null(result[target].Source);
                    Assert.Equal(target, result[target].Package);
                    Assert.True(result[target].IsComplete);
                    Assert.NotNull(downloadResult.PackageStream);
                    Assert.Equal(DownloadResourceResultStatus.Available, downloadResult.Status);
                }
        }
        private static IEnumerable <NuGetProjectAction> GetProjectActions(
            PackageIdentity packageIdentity,
            IReadOnlyCollection <PackageIdentity> packagesToInstall,
            IReadOnlyCollection <SourcePackageDependencyInfo> availablePackageDependencies,
            NugetFolderProject nuGetProject)
        {
            var nuGetProjectActions = new List <NuGetProjectAction>();

            foreach (var packageToInstall in packagesToInstall)
            {
                // Find the package match based on identity
                var sourceDepInfo = availablePackageDependencies.SingleOrDefault(p => PackageIdentity.Comparer.Equals(p, packageToInstall));

                if (sourceDepInfo == null)
                {
                    // This really should never happen since dependencies have been resolved.
                    throw new InvalidOperationException($"Package '{packageIdentity}' is not found");
                }

                nuGetProjectActions.Add(NuGetProjectAction.CreateInstallProjectAction(sourceDepInfo, sourceDepInfo.Source, nuGetProject));
            }

            return(nuGetProjectActions);
        }
예제 #9
0
        public async ValueTask InstallPackagesAsync(
            string projectId,
            IReadOnlyList <PackageIdentity> packageIdentities,
            CancellationToken cancellationToken)
        {
            Assumes.NotNullOrEmpty(projectId);
            Assumes.NotNullOrEmpty(packageIdentities);

            cancellationToken.ThrowIfCancellationRequested();

            NuGetProject?project = await SolutionUtility.GetNuGetProjectAsync(
                _state.SolutionManager,
                projectId,
                cancellationToken);

            Assumes.NotNull(project);

            SourceRepository?sourceRepository = await GetSourceRepositoryAsync(cancellationToken);

            IEnumerable <NuGetProjectAction>?actions = packageIdentities
                                                       .Select(packageIdentity => NuGetProjectAction.CreateInstallProjectAction(packageIdentity, sourceRepository, project));

            NuGetPackageManager packageManager = await _state.GetPackageManagerAsync(cancellationToken);

            Assumes.NotNull(packageManager);

            INuGetProjectContext projectContext = await ServiceLocator.GetComponentModelServiceAsync <INuGetProjectContext>();

            Assumes.NotNull(projectContext);

            await packageManager.ExecuteBuildIntegratedProjectActionsAsync(
                project as BuildIntegratedNuGetProject,
                actions,
                projectContext,
                cancellationToken);
        }
        public static async Task <IEnumerable <NuGetProjectAction> > GetInstallProjectActionsAsync(
            this NuGetPackageManager packageManager,
            NugetFolderProject nuGetProject,
            PackageIdentity packageIdentity,
            ResolutionContext resolutionContext,
            INuGetProjectContext nuGetProjectContext,
            IEnumerable <SourceRepository> primarySourceRepositories,
            IEnumerable <SourceRepository> secondarySourceRepositories,
            CancellationToken token)
        {
            if (nuGetProject == null)
            {
                throw new ArgumentNullException(nameof(nuGetProject));
            }
            if (packageIdentity == null)
            {
                throw new ArgumentNullException(nameof(packageIdentity));
            }
            if (resolutionContext == null)
            {
                throw new ArgumentNullException(nameof(resolutionContext));
            }
            if (nuGetProjectContext == null)
            {
                throw new ArgumentNullException(nameof(nuGetProjectContext));
            }
            if (primarySourceRepositories == null)
            {
                throw new ArgumentNullException(nameof(primarySourceRepositories));
            }
            if (!primarySourceRepositories.Any())
            {
                throw new ArgumentException(nameof(primarySourceRepositories));
            }
            if (secondarySourceRepositories == null)
            {
                throw new ArgumentNullException(nameof(secondarySourceRepositories));
            }
            if (packageIdentity.Version == null)
            {
                throw new ArgumentNullException(nameof(packageIdentity));
            }

            var localSources = new HashSet <SourceRepository>(new SourceRepositoryComparer());

            localSources.Add(packageManager.PackagesFolderSourceRepository);
            localSources.AddRange(packageManager.GlobalPackageFolderRepositories);

            if (resolutionContext.DependencyBehavior == DependencyBehavior.Ignore)
            {
                var logger = new ProjectContextLogger(nuGetProjectContext);

                // First, check only local sources.
                var sourceRepository = await GetSourceRepositoryAsync(packageIdentity, localSources, resolutionContext.SourceCacheContext, logger, token);

                if (sourceRepository == null)
                {
                    // Else, check provided sources. We use only primary sources when we don't care about dependencies.
                    sourceRepository = await GetSourceRepositoryAsync(packageIdentity, primarySourceRepositories, resolutionContext.SourceCacheContext, logger, token);
                }

                // If still not found, we just throw an exception.
                if (sourceRepository == null)
                {
                    throw new InvalidOperationException($"Unable to find version '{packageIdentity.Version}' of package '{packageIdentity.Id}'.");
                }

                return(new[] { NuGetProjectAction.CreateInstallProjectAction(packageIdentity, sourceRepository, nuGetProject) });
            }

            var primarySources = new HashSet <SourceRepository>(new SourceRepositoryComparer());

            primarySources.AddRange(localSources);
            primarySources.AddRange(primarySourceRepositories);

            var allSources = new HashSet <SourceRepository>(new SourceRepositoryComparer());

            allSources.AddRange(primarySources);
            allSources.AddRange(secondarySourceRepositories);

            // Get the available package dependencies.
            var packageDependencies = await GetAvailablePackageDependencies(
                packageManager,
                nuGetProject,
                packageIdentity,
                resolutionContext,
                nuGetProjectContext,
                primarySources,
                allSources,
                token);

            if (!packageDependencies.Any())
            {
                throw new InvalidOperationException($"Unable to gather dependency information for package '{packageIdentity}'");
            }

            // Prune the results down to only what we would allow to be installed.
            packageDependencies = PruneAvailablePackageDependencies(packageIdentity, resolutionContext, packageDependencies);

            // Get the actual packages to install.
            var packagesToInstall = GetPackagesToInstall(
                packageIdentity,
                resolutionContext,
                nuGetProjectContext,
                packageDependencies,
                allSources,
                token);

            if (packagesToInstall == null || !packagesToInstall.Any())
            {
                throw new InvalidOperationException($"Unable to resolve dependencies for package '{packageIdentity}' with DependencyBehavior '{resolutionContext.DependencyBehavior}'");
            }

            // Create the install actions.
            return(GetProjectActions(
                       packageIdentity,
                       packagesToInstall,
                       packageDependencies,
                       nuGetProject));
        }
예제 #11
0
        public async Task PackagePreFetcher_UpdateMultiplePackages()
        {
            using (var sourceDir = TestDirectory.Create())
                using (var packagesFolderDir = TestDirectory.Create())
                    using (var globalPackagesFolder = TestDirectory.Create())
                    {
                        // Arrange
                        var actions        = new List <NuGetProjectAction>();
                        var packagesFolder = new FolderNuGetProject(packagesFolderDir);
                        var testSettings   = new Configuration.NullSettings();
                        var logger         = new TestLogger();


                        var targetA1 = new PackageIdentity("packageA", NuGetVersion.Parse("1.0.0"));
                        var targetA2 = new PackageIdentity("packageA", NuGetVersion.Parse("2.0.0"));
                        var targetB1 = new PackageIdentity("packageB", NuGetVersion.Parse("1.0.0"));
                        var targetB2 = new PackageIdentity("packageB", NuGetVersion.Parse("2.0.0"));
                        var targetC2 = new PackageIdentity("packageC", NuGetVersion.Parse("2.0.0"));

                        var source = Repository.Factory.GetVisualStudio(new Configuration.PackageSource(sourceDir.Path));

                        // Add packages
                        AddToPackagesFolder(targetA1, packagesFolderDir);
                        AddToPackagesFolder(targetB1, packagesFolderDir);
                        AddToPackagesFolder(targetA2, packagesFolderDir);

                        // Update A and B, install C, A already exists
                        actions.Add(NuGetProjectAction.CreateUninstallProjectAction(targetA1, packagesFolder));
                        actions.Add(NuGetProjectAction.CreateUninstallProjectAction(targetB1, packagesFolder));

                        actions.Add(NuGetProjectAction.CreateInstallProjectAction(targetC2, source, packagesFolder));
                        actions.Add(NuGetProjectAction.CreateInstallProjectAction(targetB2, source, packagesFolder));
                        actions.Add(NuGetProjectAction.CreateInstallProjectAction(targetA2, source, packagesFolder));

                        AddToSource(targetA2, sourceDir);
                        AddToSource(targetB2, sourceDir);
                        AddToSource(targetC2, sourceDir);

                        // Act
                        using (var cacheContext = new SourceCacheContext())
                        {
                            var result = await PackagePreFetcher.GetPackagesAsync(
                                actions,
                                packagesFolder,
                                new PackageDownloadContext(cacheContext),
                                globalPackagesFolder,
                                logger,
                                CancellationToken.None);

                            var resultA2 = await result[targetA2].GetResultAsync();
                            var resultB2 = await result[targetB2].GetResultAsync();
                            var resultC2 = await result[targetC2].GetResultAsync();

                            // Assert
                            Assert.Equal(3, result.Count);

                            Assert.True(result[targetA2].InPackagesFolder);
                            Assert.Null(result[targetA2].Source);
                            Assert.Equal(targetA2, result[targetA2].Package);
                            Assert.True(result[targetA2].IsComplete);
                            Assert.Equal(targetA2, resultA2.PackageReader.GetIdentity());
                            Assert.NotNull(resultA2.PackageStream);
                            Assert.Equal(DownloadResourceResultStatus.Available, resultA2.Status);

                            Assert.False(result[targetB2].InPackagesFolder);
                            Assert.Equal(source.PackageSource, result[targetB2].Source);
                            Assert.Equal(targetB2, result[targetB2].Package);
                            Assert.True(result[targetB2].IsComplete);
                            Assert.Equal(targetB2, resultB2.PackageReader.GetIdentity());
                            Assert.NotNull(resultB2.PackageStream);
                            Assert.Equal(DownloadResourceResultStatus.Available, resultB2.Status);

                            Assert.False(result[targetC2].InPackagesFolder);
                            Assert.Equal(source.PackageSource, result[targetC2].Source);
                            Assert.Equal(targetC2, result[targetC2].Package);
                            Assert.True(result[targetC2].IsComplete);
                            Assert.Equal(targetC2, resultC2.PackageReader.GetIdentity());
                            Assert.NotNull(resultC2.PackageStream);
                            Assert.Equal(DownloadResourceResultStatus.Available, resultC2.Status);
                        }
                    }
        }
        NuGetProjectAction CreateUninstallProjectAction(string packageId)
        {
            var package = new PackageIdentity(packageId, null);

            return(NuGetProjectAction.CreateUninstallProjectAction(package, project));
        }
        /// <summary>
        /// Install a NuGet package. Returns all newly installed packages.
        /// </summary>
        public async Task <IReadOnlyCollection <InteractivePackage> > InstallPackageAsync(
            InteractivePackage package,
            SourceRepository sourceRepository,
            CancellationToken cancellationToken)
        {
            if (package == null)
            {
                throw new ArgumentNullException(nameof(package));
            }
            if (!package.Identity.HasVersion)
            {
                throw new ArgumentException("PackageIdentity.Version must be set");
            }

            // TODO: File upstream issue about exception if primary source repo is offline.
            //       Shouldn't secondary source repos kick in? Our current work around is to
            //       pass the source repo from search to install, but that's not perfect.
            sourceRepository = sourceRepository ?? SourceRepositories [0];

            project.ResetInstallationContext();

            // Just need to apply one fixup here
            if (PackageIdComparer.Equals(package.Identity.Id, FixedXamarinFormsPackageIdentity.Id) &&
                package.Identity.Version != FixedXamarinFormsPackageIdentity.Version)
            {
                Log.Warning(
                    TAG,
                    $"Replacing requested Xamarin.Forms version {package.Identity.Version} with " +
                    $"required version {FixedXamarinFormsPackageIdentity.Version}.");
                package = package.WithVersion(
                    FixedXamarinFormsPackageIdentity.Version,
                    overwriteRange: true);
            }

            if (PackageIdComparer.Equals(package.Identity.Id, IntegrationPackageId))
            {
                Log.Warning(TAG, $"Refusing to add integration NuGet package {IntegrationPackageId}.");
                return(Array.Empty <InteractivePackage> ());
            }

            var resolutionContext = new ResolutionContext(
                DependencyBehavior.Lowest, // IDEs only use Highest if upgrading
                includePrelease: true,
                includeUnlisted: true,
                versionConstraints: VersionConstraints.None);

            // Although there is a single repo associated with the package being installed,
            // dependency resolution will also look into the secondary sources. In some cases,
            // this can greatly slow down installation. For the primary case of searching for
            // packages in nuget.org, prevent the package manager from using secondary sources
            // for resolution.
            //
            // It is important to pass an empty enumerable, because if we pass null, the package
            // manager will determine secondary sources based on the NuGet configuration.
            var secondarySources =
                sourceRepository == SourceRepositories [0]
                ? Enumerable.Empty <SourceRepository> ()
                : SourceRepositories.Where(r => r != sourceRepository).ToArray();

            // There does not appear to be a way to hook into or override functionality of the
            // NuGetPackageManager or PackageResolver classes. In order to mess with package
            // resolution, we need to either write a lot of code, proxy the sources, or intercede
            // via preview installation actions.
            //
            // Here we do the latter, though it is not the best general-purpose approach. It works
            // fine for replacing one single package that we know a LOT about. If that package's
            // dependencies continually changed, we'd be better off with another approach.
            var previewInstallActions = await packageManager.PreviewInstallPackageAsync(
                project,
                package.Identity,
                resolutionContext,
                projectContext,
                sourceRepository,
                secondarySources,
                cancellationToken);

            var installActions = new List <NuGetProjectAction> ();

            foreach (var action in previewInstallActions)
            {
                // If the installed package has a dependency on Xamarin.Forms, make sure the version
                // that gets installed is our preferred version. Force it to install from the primary
                // source repository, because we can't assume that version is available everywhere.
                //
                // TODO: Consider adding a search or something to see if we can use the specified source
                //       instead. Could be handy if nuget.org is down or the user is offline and using
                //       a local repo.
                if (action.PackageIdentity.Id == FixedXamarinFormsPackageIdentity.Id)
                {
                    installActions.Add(NuGetProjectAction.CreateInstallProjectAction(
                                           FixedXamarinFormsPackageIdentity,
                                           SourceRepositories [0],
                                           action.Project));
                }
                else
                {
                    installActions.Add(action);
                }
            }

            // We follow the modern behavior of .NET Core and do not actually install packages anywhere.
            // Instead, we ultimately reference them out of the user's global package cache (by default,
            // ~/.nuget/packages). Our NuGetProject implementation simply collects package assembly
            // references (and potentially other necessary files) and populates them back into the
            // InteractiveInstallationContext.
            using (var sourceCacheContext = new SourceCacheContext())
                await packageManager.ExecuteNuGetProjectActionsAsync(
                    project,
                    installActions,
                    projectContext,
                    sourceCacheContext,
                    cancellationToken);

            // Identify which packages were not already noted as installed, or have been upgraded now
            var newlyInstalledPackages = new List <InteractivePackage> ();

            foreach (var newPackage in project.InstallationContext.InstalledPackages)
            {
                InteractivePackage finalNewPackage;
                var foundInstalledMatch = installedPackages.TryGetValue(
                    newPackage,
                    out finalNewPackage);

                if (!foundInstalledMatch ||
                    newPackage.Identity.Version > finalNewPackage.Identity.Version)
                {
                    // Make sure we have a reference to a matching explicit InteractivePackage if it
                    // exists, so that we can persist the original SupportedVersionRange
                    if (!foundInstalledMatch)
                    {
                        finalNewPackage = PackageIdComparer.Equals(package, newPackage)
                            ? package
                            : newPackage;
                    }

                    finalNewPackage = newPackage
                                      .WithIsExplicit(finalNewPackage.IsExplicit)
                                      .WithSupportedVersionRange(finalNewPackage.SupportedVersionRange);

                    newlyInstalledPackages.Add(finalNewPackage);
                    installedPackages = installedPackages
                                        .Remove(finalNewPackage)
                                        .Add(finalNewPackage);
                    UpdateInstalledPackages();
                }
            }

            return(newlyInstalledPackages);
        }
예제 #14
0
 bool IsInstallActionForPackageBeingUpdated(NuGetProjectAction action)
 {
     return(action.PackageIdentity.Id == PackageId &&
            action.NuGetProjectActionType == NuGetProjectActionType.Install);
 }
예제 #15
0
        internal static async Task <string> DoUpgradeAsync(
            INuGetUIContext context,
            INuGetUI uiService,
            NuGetProject nuGetProject,
            IEnumerable <NuGetProjectUpgradeDependencyItem> upgradeDependencyItems,
            IEnumerable <PackageIdentity> notFoundPackages,
            IProgress <ProgressDialogData> progress,
            CancellationToken token)
        {
            var startTime     = DateTimeOffset.Now;
            var packagesCount = 0;
            var status        = NuGetOperationStatus.Succeeded;


            using (var telemetry = new TelemetryActivity(Guid.Empty))
            {
                try
                {
                    // 0. Fail if any package was not found
                    if (notFoundPackages.Any())
                    {
                        status = NuGetOperationStatus.Failed;
                        var notFoundPackageIds = string.Join(",", notFoundPackages.Select(t => t.Id));
                        uiService.ProjectContext.Log(MessageLevel.Error, string.Format(CultureInfo.CurrentCulture, Resources.Migrator_PackageNotFound, notFoundPackageIds));
                        return(null);
                    }

                    // 1. Backup files (csproj and packages.config) that will change
                    var solutionManager           = context.SolutionManager;
                    var msBuildNuGetProject       = (MSBuildNuGetProject)nuGetProject;
                    var msBuildNuGetProjectSystem = msBuildNuGetProject.ProjectSystem;
                    var backupPath = string.Empty;
                    try
                    {
                        backupPath = CreateBackup(msBuildNuGetProject, solutionManager.SolutionDirectory);
                    }
                    catch (Exception ex)
                    {
                        status = NuGetOperationStatus.Failed;
                        // log error message
                        uiService.ShowError(ex);
                        uiService.ProjectContext.Log(MessageLevel.Info,
                                                     string.Format(CultureInfo.CurrentCulture, Resources.Upgrader_BackupFailed));

                        return(null);
                    }


                    // 2. Uninstall all packages currently in packages.config
                    var progressData = new ProgressDialogData(Resources.NuGetUpgrade_WaitMessage, Resources.NuGetUpgrade_Progress_Uninstalling);
                    progress.Report(progressData);

                    // Don't uninstall packages we couldn't find - that will just fail
                    var actions = upgradeDependencyItems.Select(d => d.Package)
                                  .Where(p => !notFoundPackages.Contains(p))
                                  .Select(t => NuGetProjectAction.CreateUninstallProjectAction(t, nuGetProject));

                    try
                    {
                        await context.PackageManager.ExecuteNuGetProjectActionsAsync(nuGetProject, actions, uiService.ProjectContext, NullSourceCacheContext.Instance, CancellationToken.None);
                    }
                    catch (Exception ex)
                    {
                        status = NuGetOperationStatus.Failed;
                        // log error message
                        uiService.ShowError(ex);
                        uiService.ProjectContext.Log(MessageLevel.Info,
                                                     string.Format(CultureInfo.CurrentCulture, Resources.Upgrade_UninstallFailed));

                        return(null);
                    }

                    // Reload the project, and get a reference to the reloaded project
                    var uniqueName = msBuildNuGetProjectSystem.ProjectUniqueName;
                    await msBuildNuGetProject.SaveAsync(token);

                    nuGetProject = await solutionManager.GetNuGetProjectAsync(uniqueName);

                    nuGetProject = await solutionManager.UpgradeProjectToPackageReferenceAsync(nuGetProject);

                    // Ensure we use the updated project for installing, and don't display preview or license acceptance windows.
                    context.Projects = new[] { nuGetProject };
                    var nuGetUI = (NuGetUI)uiService;
                    nuGetUI.Projects             = new[] { nuGetProject };
                    nuGetUI.DisplayPreviewWindow = false;

                    // 4. Install the requested packages
                    var ideExecutionContext = uiService.ProjectContext.ExecutionContext as IDEExecutionContext;
                    if (ideExecutionContext != null)
                    {
                        await ideExecutionContext.SaveExpandedNodeStates(solutionManager);
                    }

                    progressData = new ProgressDialogData(Resources.NuGetUpgrade_WaitMessage, Resources.NuGetUpgrade_Progress_Installing);
                    progress.Report(progressData);
                    var activeSources = new List <SourceRepository>();
                    PackageSourceMoniker
                    .PopulateList(context.SourceProvider)
                    .ForEach(s => activeSources.AddRange(s.SourceRepositories));
                    var packagesToInstall = GetPackagesToInstall(upgradeDependencyItems).ToList();
                    packagesCount = packagesToInstall.Count;

                    // create low level NuGet actions based on number of packages being installed
                    var lowLevelActions = new List <NuGetProjectAction>();
                    foreach (var packageIdentity in packagesToInstall)
                    {
                        lowLevelActions.Add(NuGetProjectAction.CreateInstallProjectAction(packageIdentity, activeSources.FirstOrDefault(), nuGetProject));
                    }

                    try
                    {
                        var buildIntegratedProject = nuGetProject as BuildIntegratedNuGetProject;
                        await context.PackageManager.ExecuteBuildIntegratedProjectActionsAsync(
                            buildIntegratedProject,
                            lowLevelActions,
                            uiService.ProjectContext,
                            token);

                        if (ideExecutionContext != null)
                        {
                            await ideExecutionContext.CollapseAllNodes(solutionManager);
                        }

                        return(backupPath);
                    }
                    catch (Exception ex)
                    {
                        status = NuGetOperationStatus.Failed;

                        uiService.ShowError(ex);
                        uiService.ProjectContext.Log(MessageLevel.Info,
                                                     string.Format(CultureInfo.CurrentCulture, Resources.Upgrade_InstallFailed, backupPath));
                        uiService.ProjectContext.Log(MessageLevel.Info,
                                                     string.Format(CultureInfo.CurrentCulture, Resources.Upgrade_RevertSteps, "https://aka.ms/nugetupgraderevertv1"));

                        return(null);
                    }
                }
                catch (Exception ex)
                {
                    status = NuGetOperationStatus.Failed;
                    uiService.ShowError(ex);
                    return(null);
                }
                finally
                {
                    telemetry.TelemetryEvent = VSTelemetryServiceUtility.GetUpgradeTelemetryEvent(
                        uiService.Projects,
                        status,
                        packagesCount);
                }
            }
        }
        public static async Task <IEnumerable <NuGetProjectAction> > GetInstallProjectActionsAsync(
            this NuGetPackageManager packageManager,
            NugetFolderProject nuGetProject,
            PackageIdentity packageIdentity,
            ResolutionContext resolutionContext,
            INuGetProjectContext nuGetProjectContext,
            IEnumerable <SourceRepository> primarySourceRepositories,
            IEnumerable <SourceRepository> secondarySourceRepositories,
            CancellationToken token)
        {
            if (nuGetProject == null)
            {
                throw new ArgumentNullException(nameof(nuGetProject));
            }
            if (packageIdentity == null)
            {
                throw new ArgumentNullException(nameof(packageIdentity));
            }
            if (resolutionContext == null)
            {
                throw new ArgumentNullException(nameof(resolutionContext));
            }
            if (nuGetProjectContext == null)
            {
                throw new ArgumentNullException(nameof(nuGetProjectContext));
            }
            if (primarySourceRepositories == null)
            {
                throw new ArgumentNullException(nameof(primarySourceRepositories));
            }
            if (!primarySourceRepositories.Any())
            {
                throw new ArgumentException(nameof(primarySourceRepositories));
            }
            if (secondarySourceRepositories == null)
            {
                throw new ArgumentNullException(nameof(secondarySourceRepositories));
            }
            if (packageIdentity.Version == null)
            {
                throw new ArgumentNullException(nameof(packageIdentity));
            }

            var localSources = new HashSet <SourceRepository>(new SourceRepositoryComparer());

            localSources.Add(packageManager.PackagesFolderSourceRepository);
            localSources.AddRange(packageManager.GlobalPackageFolderRepositories);

            if (resolutionContext.DependencyBehavior == DependencyBehavior.Ignore)
            {
                var logger = new ProjectContextLogger(nuGetProjectContext);

                // First, check only local sources.
                var sourceRepository = await GetSourceRepositoryAsync(packageIdentity, localSources, resolutionContext.SourceCacheContext, logger, token);

                if (sourceRepository == null)
                {
                    // Else, check provided sources. We use only primary sources when we don't care about dependencies.
                    sourceRepository = await GetSourceRepositoryAsync(packageIdentity, primarySourceRepositories, resolutionContext.SourceCacheContext, logger, token);
                }

                // If still not found, we just throw an exception.
                if (sourceRepository == null)
                {
                    throw new InvalidOperationException($"Unable to find version '{packageIdentity.Version}' of package '{packageIdentity.Id}'.");
                }

                return(new[] { NuGetProjectAction.CreateInstallProjectAction(packageIdentity, sourceRepository, nuGetProject) });
            }

            var primarySources = new HashSet <SourceRepository>(new SourceRepositoryComparer());
            var allSources     = new HashSet <SourceRepository>(new SourceRepositoryComparer());

            Tuple <IReadOnlyCollection <PackageIdentity>, IReadOnlyCollection <SourcePackageDependencyInfo> > packageAndDependencies = null;
            var allDependenciesResolved = false;

            // If target package is already installed, there's a slight chance that all packages are already installed.
            if (await PackageExistsInSourceRepository(
                    packageIdentity,
                    packageManager.PackagesFolderSourceRepository,
                    resolutionContext.SourceCacheContext,
                    new ProjectContextLogger(nuGetProjectContext),
                    token))
            {
                primarySources.Add(packageManager.PackagesFolderSourceRepository);
                allSources.Add(packageManager.PackagesFolderSourceRepository);

                try
                {
                    // Try get all dependencies from local sources only.
                    packageAndDependencies = await GetPackageAndDependenciesToInstall(
                        packageManager,
                        nuGetProject,
                        packageIdentity,
                        resolutionContext,
                        nuGetProjectContext,
                        primarySources,
                        allSources,
                        token);

                    allDependenciesResolved = true;
                }
                catch (NuGetResolverConstraintException)
                {
                    // We didn't manage to find all dependencies in the local packages folder.
                    allDependenciesResolved = false;
                }
            }

            // If we didn't manage to resolve all dependencies from the local sources, check in all sources.
            if (!allDependenciesResolved)
            {
                primarySources.AddRange(localSources);
                primarySources.AddRange(primarySourceRepositories);
                allSources.AddRange(primarySources);
                allSources.AddRange(secondarySourceRepositories);

                packageAndDependencies = await GetPackageAndDependenciesToInstall(
                    packageManager,
                    nuGetProject,
                    packageIdentity,
                    resolutionContext,
                    nuGetProjectContext,
                    primarySources,
                    allSources,
                    token);
            }

            // Create the install actions.
            return(GetProjectActions(
                       packageIdentity,
                       packageAndDependencies.Item1,
                       packageAndDependencies.Item2,
                       nuGetProject));
        }