/// <summary>
        /// Устанавливает пакет.
        /// </summary>
        /// <param name="packageId">ID пакета.</param>
        /// <param name="packageVersion">Версия пакета.</param>
        /// <param name="allowPrerelease">Разрешена ли установка предварительного релиза.</param>
        /// <returns>Содержимое установленного пакета.</returns>
        public async Task<PackageContent> InstallPackage(string packageId, string packageVersion = null, bool allowPrerelease = false)
        {
            NuGetVersion packageNuGetVersion = null;

            if (!string.IsNullOrWhiteSpace(packageVersion))
            {
                packageNuGetVersion = NuGetVersion.Parse(packageVersion);
            }

            // Конфигурационный файл NuGet.config по умолчанию
            var settings = new NuGet.Configuration.Settings(_packagesPath, "NuGet.config");

            // Фабрика источников пактов на основе конфигурационного файла
            var packageSourceProvider = new PackageSourceProvider(settings);

            // Добавление в фабрику источников пакетов дополнительных источников
            packageSourceProvider.SavePackageSources(_packageSources.Select(i => new PackageSource(i)));

            // Фабрика хранилищ пакетов на основе фабрики источников пакетов
            var packageRepositoryProvider = new CachingSourceProvider(packageSourceProvider);

            // Получение всех хранилищ пакетов на основе указанных источников
            var packageRepositories = packageRepositoryProvider.GetRepositories().ToList();

            // Определение возможности установки prerelease-версии пакетов
            allowPrerelease = allowPrerelease || (packageNuGetVersion != null && packageNuGetVersion.IsPrerelease);

            // Создание правил разрешения зависимостей при установке пакета
            var resolutionContext = new ResolutionContext(
                dependencyBehavior: DependencyBehavior.Lowest,
                includePrelease: allowPrerelease,
                includeUnlisted: true,
                versionConstraints: VersionConstraints.None);

            // Если версия пакета не указана, поиск последней версии
            if (packageNuGetVersion == null)
            {
                packageNuGetVersion = await NuGetPackageManager.GetLatestVersionAsync(
                    packageId,
                    NuGetFramework.AnyFramework,
                    resolutionContext,
                    packageRepositories,
                    _logger,
                    CancellationToken.None);

                if (packageNuGetVersion == null)
                {
                    throw new InvalidOperationException(string.Format(Properties.Resources.PackageNotFound, packageId));
                }
            }

            // Уникальный идентификатор версии пакета для установки
            var packageIdentity = new PackageIdentity(packageId, packageNuGetVersion);

            // Каталог для установки пакетов (каталог packages)
            NuGetProject folderProject = new InfinniFolderNuGetProject(_packagesPath);
            
            // Менеджер для управления пакетами
            var packageManager = new NuGetPackageManager(packageRepositoryProvider, settings, _packagesPath);

            // Правила установки пакетов
            var projectContext = new NuGetLoggerProjectContext(_logger)
            {
                PackageExtractionContext = new PackageExtractionContext
                {
                    PackageSaveMode = PackageSaveMode.Defaultv3
                }
            };

            // Определение порядка действий при установке пакета
            var installActions = (await packageManager.PreviewInstallPackageAsync(
                folderProject,
                packageIdentity,
                resolutionContext,
                projectContext,
                packageRepositories,
                Enumerable.Empty<SourceRepository>(),
                CancellationToken.None)).ToList();

            // Применение действий по установке пакета
            await packageManager.ExecuteNuGetProjectActionsAsync(
                folderProject,
                installActions,
                projectContext,
                CancellationToken.None);

            return GetPackageContent(packageIdentity, installActions.Select(i => i.PackageIdentity).ToList());
        }
        public async Task TestPacManPreviewInstallOrderOfDependencies()
        {
            // Arrange
            var sourceRepositoryProvider = TestSourceRepositoryUtility.CreateV2OnlySourceRepositoryProvider();
            var testSolutionManager = new TestSolutionManager();
            var testSettings = new NullSettings();
            var token = CancellationToken.None;
            var nuGetPackageManager = new NuGetPackageManager(sourceRepositoryProvider, testSettings, testSolutionManager);
            var packagesFolderPath = PackagesFolderPathUtility.GetPackagesFolderPath(testSolutionManager, testSettings);

            var randomPackagesConfigFolderPath = TestFilesystemUtility.CreateRandomTestFolder();
            var randomPackagesConfigPath = Path.Combine(randomPackagesConfigFolderPath, "packages.config");

            var projectTargetFramework = NuGetFramework.Parse("net45");
            var msBuildNuGetProjectSystem = new TestMSBuildNuGetProjectSystem(projectTargetFramework, new TestNuGetProjectContext());
            var msBuildNuGetProject = new MSBuildNuGetProject(msBuildNuGetProjectSystem, packagesFolderPath, randomPackagesConfigPath);
            var packageIdentity = MorePackageWithDependents[3];

            // Pre-Assert
            // Check that the packages.config file does not exist
            Assert.False(File.Exists(randomPackagesConfigPath));
            // Check that there are no packages returned by PackagesConfigProject
            var packagesInPackagesConfig = (await msBuildNuGetProject.PackagesConfigNuGetProject.GetInstalledPackagesAsync(token)).ToList();
            Assert.Equal(0, packagesInPackagesConfig.Count);
            Assert.Equal(0, msBuildNuGetProjectSystem.References.Count);

            // Act
            var packageActions = (await nuGetPackageManager.PreviewInstallPackageAsync(msBuildNuGetProject, packageIdentity,
                new ResolutionContext(), new TestNuGetProjectContext(), sourceRepositoryProvider.GetRepositories().First(), null, token)).ToList();

            // Assert
            Assert.Equal(3, packageActions.Count);
            Assert.True(MorePackageWithDependents[0].Equals(packageActions[0].PackageIdentity));
            Assert.Equal(NuGetProjectActionType.Install, packageActions[0].NuGetProjectActionType);
            Assert.Equal(sourceRepositoryProvider.GetRepositories().Single().PackageSource.Source,
                packageActions[0].SourceRepository.PackageSource.Source);
            Assert.True(MorePackageWithDependents[2].Equals(packageActions[1].PackageIdentity));
            Assert.Equal(NuGetProjectActionType.Install, packageActions[1].NuGetProjectActionType);
            Assert.Equal(sourceRepositoryProvider.GetRepositories().Single().PackageSource.Source,
                packageActions[0].SourceRepository.PackageSource.Source);
            Assert.True(MorePackageWithDependents[3].Equals(packageActions[2].PackageIdentity));
            Assert.Equal(NuGetProjectActionType.Install, packageActions[2].NuGetProjectActionType);
            Assert.Equal(sourceRepositoryProvider.GetRepositories().Single().PackageSource.Source,
                packageActions[0].SourceRepository.PackageSource.Source);


            // Clean-up
            TestFilesystemUtility.DeleteRandomTestFolders(testSolutionManager.SolutionDirectory, randomPackagesConfigFolderPath);
        }
        public async Task TestPacManPreviewInstallDependencyVersionHighestAndPrerelease()
        {
            // Arrange
            var sourceRepositoryProvider = TestSourceRepositoryUtility.CreateV3OnlySourceRepositoryProvider();
            var testSolutionManager = new TestSolutionManager();
            var testSettings = new NullSettings();
            var token = CancellationToken.None;
            var nuGetPackageManager = new NuGetPackageManager(sourceRepositoryProvider, testSettings, testSolutionManager);
            var packagesFolderPath = PackagesFolderPathUtility.GetPackagesFolderPath(testSolutionManager, testSettings);

            var randomPackagesConfigFolderPath = TestFilesystemUtility.CreateRandomTestFolder();
            var randomPackagesConfigPath = Path.Combine(randomPackagesConfigFolderPath, "packages.config");
            var primarySourceRepository = sourceRepositoryProvider.GetRepositories().First();

            var projectTargetFramework = NuGetFramework.Parse("net45");
            var msBuildNuGetProjectSystem = new TestMSBuildNuGetProjectSystem(projectTargetFramework, new TestNuGetProjectContext());
            var msBuildNuGetProject = new MSBuildNuGetProject(msBuildNuGetProjectSystem, packagesFolderPath, randomPackagesConfigPath);
            var dotnetrdfPackageIdentity = new PackageIdentity("dotnetrdf", new NuGetVersion("1.0.8-prerelease1"));
            var resolutionContext = new ResolutionContext(DependencyBehavior.Highest, includePrelease: true);

            var newtonsoftJsonPackageId = "newtonsoft.json";

            // Act
            NuGetVersion latestNewtonsoftPrereleaseVersion = await NuGetPackageManager.GetLatestVersionAsync(newtonsoftJsonPackageId, resolutionContext, primarySourceRepository, CancellationToken.None);
            var newtonsoftJsonPackageIdentity = new PackageIdentity(newtonsoftJsonPackageId, latestNewtonsoftPrereleaseVersion);

            var nuGetProjectActions = (await nuGetPackageManager.PreviewInstallPackageAsync(msBuildNuGetProject, dotnetrdfPackageIdentity, resolutionContext,
                new TestNuGetProjectContext(), primarySourceRepository, null, CancellationToken.None)).ToList();

            // Assert
            Assert.Equal(4, nuGetProjectActions.Count);
            var newtonsoftJsonAction = nuGetProjectActions.Where(a => a.PackageIdentity.Equals(newtonsoftJsonPackageIdentity)).FirstOrDefault();

            Assert.NotNull(newtonsoftJsonAction);
        }
        public async Task TestPacManPreviewInstallWithAllowedVersionsConstraint()
        {
            // Arrange
            var sourceRepositoryProvider = TestSourceRepositoryUtility.CreateV2OnlySourceRepositoryProvider();
            var testSolutionManager = new TestSolutionManager();
            var testSettings = new NullSettings();
            var token = CancellationToken.None;
            var nuGetPackageManager = new NuGetPackageManager(sourceRepositoryProvider, testSettings, testSolutionManager);
            var packagesFolderPath = PackagesFolderPathUtility.GetPackagesFolderPath(testSolutionManager, testSettings);

            var randomPackagesConfigFolderPath = TestFilesystemUtility.CreateRandomTestFolder();
            var randomPackagesConfigPath = Path.Combine(randomPackagesConfigFolderPath, "packages.config");

            var projectTargetFramework = NuGetFramework.Parse("net45");
            var msBuildNuGetProjectSystem = new TestMSBuildNuGetProjectSystem(projectTargetFramework, new TestNuGetProjectContext());
            var msBuildNuGetProject = new MSBuildNuGetProject(msBuildNuGetProjectSystem, packagesFolderPath, randomPackagesConfigPath);
            var newtonsoftJsonPackageId = "newtonsoft.json";
            var newtonsoftJsonPackageIdentity = new PackageIdentity(newtonsoftJsonPackageId, NuGetVersion.Parse("4.5.11"));
            var primarySourceRepository = sourceRepositoryProvider.GetRepositories().Single();
            var resolutionContext = new ResolutionContext();
            var testNuGetProjectContext = new TestNuGetProjectContext();

            // Act
            await nuGetPackageManager.InstallPackageAsync(msBuildNuGetProject, newtonsoftJsonPackageIdentity,
                resolutionContext, testNuGetProjectContext, primarySourceRepository, null, token);

            // Assert
            // Check that the packages.config file exists after the installation
            Assert.True(File.Exists(randomPackagesConfigPath));
            // Check the number of packages and packages returned by PackagesConfigProject after the installation
            var packagesInPackagesConfig = (await msBuildNuGetProject.PackagesConfigNuGetProject.GetInstalledPackagesAsync(token)).ToList();
            Assert.Equal(1, packagesInPackagesConfig.Count);
            Assert.Equal(newtonsoftJsonPackageIdentity, packagesInPackagesConfig[0].PackageIdentity);
            Assert.Equal(projectTargetFramework, packagesInPackagesConfig[0].TargetFramework);
            var installedPackages = await msBuildNuGetProject.GetInstalledPackagesAsync(token);
            var newtonsoftJsonPackageReference = installedPackages.Where(pr => pr.PackageIdentity.Equals(newtonsoftJsonPackageIdentity)).FirstOrDefault();

            Assert.Null(newtonsoftJsonPackageReference.AllowedVersions);

            const string newPackagesConfig = @"<?xml version='1.0' encoding='utf-8'?>
  <packages>
    <package id='Newtonsoft.Json' version='4.5.11' allowedVersions='[4.0,5.0)' targetFramework='net45' />
  </packages> ";

            File.WriteAllText(randomPackagesConfigPath, newPackagesConfig);

            // Check that the packages.config file exists after the installation
            Assert.True(File.Exists(randomPackagesConfigPath));
            // Check the number of packages and packages returned by PackagesConfigProject after the installation
            packagesInPackagesConfig = (await msBuildNuGetProject.PackagesConfigNuGetProject.GetInstalledPackagesAsync(token)).ToList();
            Assert.Equal(1, packagesInPackagesConfig.Count);
            Assert.Equal(newtonsoftJsonPackageIdentity, packagesInPackagesConfig[0].PackageIdentity);
            Assert.Equal(projectTargetFramework, packagesInPackagesConfig[0].TargetFramework);
            installedPackages = await msBuildNuGetProject.GetInstalledPackagesAsync(token);
            newtonsoftJsonPackageReference = installedPackages.Where(pr => pr.PackageIdentity.Equals(newtonsoftJsonPackageIdentity)).FirstOrDefault();

            Assert.NotNull(newtonsoftJsonPackageReference.AllowedVersions);

            Exception exception = null;
            try
            {
                // Main Act
                await nuGetPackageManager.PreviewInstallPackageAsync(msBuildNuGetProject, newtonsoftJsonPackageId,
                    resolutionContext, testNuGetProjectContext, primarySourceRepository, null, token);
            }
            catch (Exception ex)
            {
                exception = ex;
            }

            Assert.NotNull(exception);
        }
        public async Task TestPacManPreviewInstallPackageThrowsDependencyDowngrade()
        {
            // Arrange
            var packageIdentityA = new PackageIdentity("DotNetOpenAuth.OAuth.Core", new NuGetVersion("4.3.2.13293"));
            var packageIdentityB1 = new PackageIdentity("DotNetOpenAuth.Core", new NuGetVersion("4.3.2.13293"));
            var packageIdentityB2 = new PackageIdentity("DotNetOpenAuth.Core", new NuGetVersion("4.3.4.13329"));
            var sourceRepositoryProvider = TestSourceRepositoryUtility.CreateV2OnlySourceRepositoryProvider();
            var testSolutionManager = new TestSolutionManager();
            var testSettings = new NullSettings();
            var token = CancellationToken.None;
            var nuGetPackageManager = new NuGetPackageManager(sourceRepositoryProvider, testSettings, testSolutionManager);
            var packagesFolderPath = PackagesFolderPathUtility.GetPackagesFolderPath(testSolutionManager, testSettings);

            var randomPackagesConfigFolderPath = TestFilesystemUtility.CreateRandomTestFolder();
            var randomPackagesConfigPath = Path.Combine(randomPackagesConfigFolderPath, "packages.config");

            var projectTargetFramework = NuGetFramework.Parse("net45");
            var msBuildNuGetProjectSystem = new TestMSBuildNuGetProjectSystem(projectTargetFramework, new TestNuGetProjectContext());
            var msBuildNuGetProject = new MSBuildNuGetProject(msBuildNuGetProjectSystem, packagesFolderPath, randomPackagesConfigPath);
            var testNuGetProjectContext = new TestNuGetProjectContext();
            var primarySourceRepository = sourceRepositoryProvider.GetRepositories().First();

            // Pre-Assert
            // Check that the packages.config file does not exist
            Assert.False(File.Exists(randomPackagesConfigPath));
            // Check that there are no packages returned by PackagesConfigProject
            var packagesInPackagesConfig = (await msBuildNuGetProject.PackagesConfigNuGetProject.GetInstalledPackagesAsync(token)).ToList();
            Assert.Equal(0, packagesInPackagesConfig.Count);
            Assert.Equal(0, msBuildNuGetProjectSystem.References.Count);

            // Act
            await nuGetPackageManager.InstallPackageAsync(msBuildNuGetProject, packageIdentityB2, new ResolutionContext(DependencyBehavior.Lowest, includePrelease: true),
                testNuGetProjectContext, primarySourceRepository, null, token);

            // Check that the packages.config file does not exist
            Assert.True(File.Exists(randomPackagesConfigPath));
            // Check that there are no packages returned by PackagesConfigProject
            packagesInPackagesConfig = (await msBuildNuGetProject.PackagesConfigNuGetProject.GetInstalledPackagesAsync(token)).ToList();
            Assert.Equal(2, packagesInPackagesConfig.Count);

            Exception exception = null;
            try
            {
                var packageActions = (await nuGetPackageManager.PreviewInstallPackageAsync(msBuildNuGetProject, packageIdentityA,
            new ResolutionContext(), testNuGetProjectContext, primarySourceRepository, null, token)).ToList();
            }
            catch (Exception ex)
            {
                exception = ex;
            }

            Assert.NotNull(exception);
            Assert.True(exception is InvalidOperationException);
            Assert.Equal("Already referencing a newer version of '" + packageIdentityB1.Id + "'..",
                exception.Message);

            // Clean-up
            TestFilesystemUtility.DeleteRandomTestFolders(testSolutionManager.SolutionDirectory, randomPackagesConfigFolderPath);
        }