예제 #1
0
        /// <summary>
        /// Fetch, if not already downloaded, and install the package represented by
        /// (<paramref name="packageId"/>, <paramref name="version"/>).
        /// </summary>
        /// <remarks>It is safe to call it concurrently be cause we operations are done using the FileLock.</remarks>
        /// <param name="packageId">Name of package to install.</param>
        /// <param name="version">Version of package to install.</param>
        public async Task <NugetLocalPackage> InstallPackage(string packageId, PackageVersion version, ProgressReport progress)
        {
            // Xenko 2.x still installs in GamePackages
            var currentManager = IsPackageV2(packageId, version) ? managerV2 : manager;

            using (GetLocalRepositoryLock())
            {
                currentProgressReport = progress;
                try
                {
                    var identity = new PackageIdentity(packageId, version.ToNuGetVersion());

                    var resolutionContext = new ResolutionContext(
                        DependencyBehavior.Lowest,
                        true,
                        true,
                        VersionConstraints.None);

                    var repositories = PackageSources.Select(sourceRepositoryProvider.CreateRepository).ToArray();

                    var projectContext = new EmptyNuGetProjectContext()
                    {
                        ActionType = NuGetActionType.Install,
                        PackageExtractionContext = new PackageExtractionContext(NativeLogger),
                    };

                    ActivityCorrelationId.StartNew();

                    {
                        // Equivalent to:
                        //   await manager.InstallPackageAsync(manager.PackagesFolderNuGetProject,
                        //       identity, resolutionContext, projectContext, repositories,
                        //       Array.Empty<SourceRepository>(),  // This is a list of secondary source respositories, probably empty
                        //       CancellationToken.None);
                        using (var sourceCacheContext = new SourceCacheContext())
                        {
                            var nuGetProject        = currentManager.PackagesFolderNuGetProject;
                            var packageIdentity     = identity;
                            var nuGetProjectContext = projectContext;
                            var primarySources      = repositories;
                            var secondarySources    = Array.Empty <SourceRepository>();
                            var token           = CancellationToken.None;
                            var downloadContext = new PackageDownloadContext(sourceCacheContext);

                            // Step-1 : Call PreviewInstallPackageAsync to get all the nuGetProjectActions
                            var nuGetProjectActions = await currentManager.PreviewInstallPackageAsync(nuGetProject, packageIdentity, resolutionContext,
                                                                                                      nuGetProjectContext, primarySources, secondarySources, token);

                            // Notify that installations started.
                            foreach (var operation in nuGetProjectActions)
                            {
                                if (operation.NuGetProjectActionType == NuGetProjectActionType.Install)
                                {
                                    var installPath = GetInstalledPath(operation.PackageIdentity.Id, operation.PackageIdentity.Version.ToPackageVersion());
                                    OnPackageInstalling(this, new PackageOperationEventArgs(new PackageName(operation.PackageIdentity.Id, operation.PackageIdentity.Version.ToPackageVersion()), installPath));
                                }
                            }

                            NuGetPackageManager.SetDirectInstall(packageIdentity, nuGetProjectContext);

                            // Step-2 : Execute all the nuGetProjectActions
                            if (IsPackageV2(packageId, version))
                            {
                                await currentManager.ExecuteNuGetProjectActionsAsync(
                                    nuGetProject,
                                    nuGetProjectActions,
                                    nuGetProjectContext,
                                    downloadContext,
                                    token);
                            }
                            else
                            {
                                // Download and install package in the global cache (can't use NuGetPackageManager anymore since it is designed for V2)
                                foreach (var operation in nuGetProjectActions)
                                {
                                    if (operation.NuGetProjectActionType == NuGetProjectActionType.Install)
                                    {
                                        using (var downloadResult = await PackageDownloader.GetDownloadResourceResultAsync(primarySources, packageIdentity, downloadContext, InstallPath, NativeLogger, token))
                                        {
                                            if (downloadResult.Status != DownloadResourceResultStatus.Available)
                                            {
                                                throw new InvalidOperationException($"Could not download package {packageIdentity}");
                                            }

                                            using (var installResult = await GlobalPackagesFolderUtility.AddPackageAsync(packageIdentity, downloadResult.PackageStream, InstallPath, NativeLogger, token))
                                            {
                                                if (installResult.Status != DownloadResourceResultStatus.Available)
                                                {
                                                    throw new InvalidOperationException($"Could not install package {packageIdentity}");
                                                }
                                            }
                                        }
                                    }
                                }
                            }

                            NuGetPackageManager.ClearDirectInstall(nuGetProjectContext);

                            // Notify that installations completed.
                            foreach (var operation in nuGetProjectActions)
                            {
                                if (operation.NuGetProjectActionType == NuGetProjectActionType.Install)
                                {
                                    var installPath = GetInstalledPath(operation.PackageIdentity.Id, operation.PackageIdentity.Version.ToPackageVersion());
                                    OnPackageInstalled(this, new PackageOperationEventArgs(new PackageName(operation.PackageIdentity.Id, operation.PackageIdentity.Version.ToPackageVersion()), installPath));
                                }
                            }
                        }
                    }

                    // Load the recently installed package
                    var installedPackages = GetPackagesInstalled(new[] { packageId });
                    return(installedPackages.FirstOrDefault(p => p.Version == version));
                }
                finally
                {
                    currentProgressReport = null;
                }
            }
        }
예제 #2
0
        internal async Task UpdateSelfFromVersionAsync(string exePath, bool prerelease, NuGetVersion currentVersion, string source, CancellationToken cancellationToken)
        {
            var sourceCacheContext = new SourceCacheContext();

            _console.WriteLine(LocalizedResourceManager.GetString("UpdateCommandCheckingForUpdates"), source);

            var sourceRepository = Repository.Factory.GetCoreV3(source);
            var metadataResource = await sourceRepository.GetResourceAsync <MetadataResource>(cancellationToken);

            var latestVersion = await metadataResource.GetLatestVersion(NuGetCommandLinePackageId, prerelease, includeUnlisted : false, sourceCacheContext, _console, cancellationToken);

            _console.WriteLine(LocalizedResourceManager.GetString("UpdateCommandCurrentlyRunningNuGetExe"), currentVersion);

            // Check to see if an update is needed
            if (latestVersion == null || currentVersion >= latestVersion)
            {
                _console.WriteLine(LocalizedResourceManager.GetString("UpdateCommandNuGetUpToDate"));
            }
            else
            {
                _console.WriteLine(LocalizedResourceManager.GetString("UpdateCommandUpdatingNuGet"), latestVersion);

                var packageIdentity = new PackageIdentity(NuGetCommandLinePackageId, latestVersion);

                var tempDir   = Path.Combine(NuGetEnvironment.GetFolderPath(NuGetFolderPath.Temp), "updateSelf");
                var nupkgPath = FileUtility.GetTempFilePath(tempDir);
                try
                {
                    DirectoryUtility.CreateSharedDirectory(tempDir);

                    DownloadResourceResult downloadResourceResult = await PackageDownloader.GetDownloadResourceResultAsync(
                        sourceRepository,
                        packageIdentity,
                        new PackageDownloadContext(sourceCacheContext),
                        tempDir,
                        _console,
                        cancellationToken);

                    // Get the exe path and move it to a temp file (NuGet.exe.old) so we can replace the running exe with the bits we got
                    // from the package repository
                    IEnumerable <string> packageFiles = await downloadResourceResult.PackageReader.GetFilesAsync(CancellationToken.None);

                    string nugetExeInPackageFilePath = packageFiles.FirstOrDefault(f => Path.GetFileName(f).Equals(NuGetExe, StringComparison.OrdinalIgnoreCase));

                    // If for some reason this package doesn't have NuGet.exe then we don't want to use it
                    if (nugetExeInPackageFilePath == null)
                    {
                        throw new CommandException(LocalizedResourceManager.GetString("UpdateCommandUnableToLocateNuGetExe"));
                    }

                    string renamedPath = exePath + ".old";

                    FileUtility.Move(exePath, renamedPath);

                    using (Stream fromStream = await downloadResourceResult.PackageReader.GetStreamAsync(nugetExeInPackageFilePath, cancellationToken), toStream = File.Create(exePath))
                    {
                        fromStream.CopyTo(toStream);
                    }
                }
                finally
                {
                    // Delete the temporary directory
                    try
                    {
                        Directory.Delete(tempDir, recursive: true);
                    }
                    catch
                    {
                    }
                }
            }
            _console.WriteLine(LocalizedResourceManager.GetString("UpdateCommandUpdateSuccessful"));
        }
예제 #3
0
        public static async Task <Dictionary <PackageIdentity, PackagePreFetcherResult> > GetPackagesAsync(
            IEnumerable <ResolvedAction> actions, IModulesDirectory modulesDirectory, PackageDownloadContext downloadContext, ILogger logger,
            CancellationToken token)
        {
            var result           = new Dictionary <PackageIdentity, PackagePreFetcherResult>();
            var maxParallelTasks = PackageManagementConstants.DefaultMaxDegreeOfParallelism;
            var toDownload       = new Queue <ResolvedAction>();
            var seen             = new HashSet <PackageIdentity>();

            // Find all uninstalled packages
            var uninstalledPackages = new HashSet <PackageIdentity>(
                actions.Where(action => action.Action == ResolvedActionType.Uninstall)
                .Select(action => action.PackageIdentity));

            // find the packages that need to be downloaded
            foreach (var action in actions)
            {
                if (action.Action == ResolvedActionType.Install && seen.Add(action.PackageIdentity))
                {
                    string localFile = null;

                    // Packages that are also being uninstalled cannot come from the
                    // packages folder since it will be gone. This is true for reinstalls.
                    if (!uninstalledPackages.Contains(action.PackageIdentity))
                    {
                        // Check the packages folder for the id and version
                        localFile = modulesDirectory.VersionFolderPathResolver.GetPackageFilePath(
                            action.PackageIdentity.Id, action.PackageIdentity.Version);

                        // Verify the nupkg exists
                        if (localFile == null || !File.Exists(localFile))
                        {
                            localFile = null;
                        }
                    }

                    // installPath will contain the full path of the already installed nupkg if it
                    // exists. If the path is empty it will need to be downloaded.
                    if (!string.IsNullOrEmpty(localFile))
                    {
                        // Create a download result using the already installed package
                        var downloadResult = new PackagePreFetcherResult(localFile, action.PackageIdentity);
                        result.Add(action.PackageIdentity, downloadResult);
                    }
                    else
                    {
                        // Download this package
                        toDownload.Enqueue(action);
                    }
                }
            }

            // Check if any packages are not already in the packages folder
            if (toDownload.Any())
            {
                var downloadResults = new List <PackagePreFetcherResult>(maxParallelTasks);

                while (toDownload.Count > 0)
                {
                    // Throttle tasks
                    if (downloadResults.Count == maxParallelTasks)
                    {
                        // Wait for a task to complete
                        // This will not throw, exceptions are stored in the result
                        await Task.WhenAny(downloadResults.Select(e => e.EnsureResultAsync()));

                        // Remove all completed tasks
                        downloadResults.RemoveAll(e => e.IsComplete);
                    }

                    var action = toDownload.Dequeue();

                    // Download the package if it does not exist in the packages folder already
                    // Start the download task
                    var task = Task.Run(async() => await PackageDownloader.GetDownloadResourceResultAsync(
                                            action.SourceRepository,
                                            action.PackageIdentity,
                                            downloadContext,
                                            "NO_GLOBAL_CACHE_DIRECTORY",
                                            logger,
                                            token), token);

                    var downloadResult = new PackagePreFetcherResult(
                        task,
                        action.PackageIdentity,
                        action.SourceRepository.PackageSource);

                    downloadResults.Add(downloadResult);
                    result.Add(action.PackageIdentity, downloadResult);
                }
            }

            // Do not wait for the remaining tasks to finish, these will download
            // in the background while other operations such as uninstall run first.
            return(result);
        }