private async Task <bool> InstallPackageAsync(RemoteMatch installItem, NuGetv3LocalRepository userPackageFolder, PackageExtractionContext packageExtractionContext, CancellationToken token)
        {
            var packageIdentity = new PackageIdentity(installItem.Library.Name, installItem.Library.Version);

            // Check if the package has already been installed.
            if (!userPackageFolder.Exists(packageIdentity.Id, packageIdentity.Version))
            {
                var versionFolderPathResolver = new VersionFolderPathResolver(_request.PackagesDirectory);

                try
                {
                    using (var packageDependency = await installItem.Provider.GetPackageDownloaderAsync(
                               packageIdentity,
                               _request.CacheContext,
                               _logger,
                               token))
                    {
                        // Install, returns true if the package was actually installed.
                        // Returns false if the package was a noop once the lock
                        // was acquired.
                        var installed = await PackageExtractor.InstallFromSourceAsync(
                            packageIdentity,
                            packageDependency,
                            versionFolderPathResolver,
                            packageExtractionContext,
                            token,
                            ParentId);

                        // 1) If another project in this process installs the package this will return false but userPackageFolder will contain the package.
                        // 2) If another process installs the package then this will also return false but we still need to update the cache.
                        // For #2 double check that the cache has the package now otherwise clear
                        if (installed || !userPackageFolder.Exists(packageIdentity.Id, packageIdentity.Version))
                        {
                            // If the package was added, clear the cache so that the next caller can see it.
                            // Avoid calling this for packages that were not actually installed.
                            userPackageFolder.ClearCacheForIds(new string[] { packageIdentity.Id });
                        }
                    }
                }
                catch (SignatureException e)
                {
                    if (!string.IsNullOrEmpty(e.Message))
                    {
                        await _logger.LogAsync(e.AsLogMessage());
                    }

                    // If the package is unsigned and unsigned packages are not allowed a SignatureException
                    // will be thrown but it won't have results because it didn't went through any
                    // verification provider.
                    if (e.Results != null)
                    {
                        await _logger.LogMessagesAsync(e.Results.SelectMany(p => p.Issues));
                    }

                    return(false);
                }
            }

            return(true);
        }
예제 #2
0
        public async Task <LocalPackageSourceInfo> EnsureLocalPackage(IRemoteDependencyProvider provider,
                                                                      PackageIdentity packageIdentity)
        {
            if (!_v3LocalRepository.Exists(packageIdentity.Id, packageIdentity.Version))
            {
                var packageDependency = await provider.GetPackageDownloaderAsync(packageIdentity, _cache, _context.Logger, CancellationToken.None);

                var installed = await PackageExtractor.InstallFromSourceAsync(
                    packageIdentity,
                    packageDependency,
                    _v3LocalRepository.PathResolver,
                    _context,
                    CancellationToken.None,
                    Guid.NewGuid());

                // 1) If another project in this process installs the package this will return false but userPackageFolder will contain the package.
                // 2) If another process installs the package then this will also return false but we still need to update the cache.
                // For #2 double check that the cache has the package now otherwise clear
                if (installed || !_v3LocalRepository.Exists(packageIdentity.Id, packageIdentity.Version))
                {
                    // If the package was added, clear the cache so that the next caller can see it.
                    // Avoid calling this for packages that were not actually installed.
                    _v3LocalRepository.ClearCacheForIds(new string[] { packageIdentity.Id });
                }
            }

            return(NuGetv3LocalRepositoryUtility.GetPackage(new[] { _v3LocalRepository }, packageIdentity.Id, packageIdentity.Version));
        }
        public async Task NuGetv3LocalRepository_FindPackagesById_InstallStress()
        {
            // Arrange
            using (var workingDir = TestDirectory.Create())
            {
                var id     = "a";
                var target = new NuGetv3LocalRepository(workingDir);

                var packages = new ConcurrentQueue <PackageIdentity>();
                var limit    = 100;

                for (int i = 0; i < limit; i++)
                {
                    packages.Enqueue(new PackageIdentity(id, NuGetVersion.Parse($"{i + 1}.0.0")));
                }

                var tasks = new List <Task>();
                var sem   = new ManualResetEventSlim(false);

                for (int i = 0; i < 10; i++)
                {
                    tasks.Add(Task.Run(async() =>
                    {
                        sem.Wait();

                        PackageIdentity identity;
                        while (packages.TryDequeue(out identity))
                        {
                            // Fetch
                            var result = target.FindPackagesById(identity.Id)
                                         .FirstOrDefault(f => f.Version == identity.Version);

                            Assert.Null(result);

                            // Create package
                            await SimpleTestPackageUtility.CreateFolderFeedV3(workingDir,
                                                                              PackageSaveMode.Defaultv3,
                                                                              identity);

                            // Clear
                            target.ClearCacheForIds(new[] { identity.Id });

                            result = target.FindPackagesById(identity.Id)
                                     .FirstOrDefault(f => f.Version == identity.Version);

                            // Assert the package was found
                            Assert.NotNull(result);
                        }
                    }));
                }

                sem.Set();
                await Task.WhenAll(tasks);

                // Assert
                var results2 = target.FindPackagesById(id);
                Assert.Equal(limit, results2.Count());
            }
        }
        public async Task NuGetv3LocalRepository_FindPackagesById_Stress()
        {
            // Arrange
            using (var workingDir = TestDirectory.Create())
            {
                var id     = "a";
                var target = new NuGetv3LocalRepository(workingDir);

                var packages = new List <PackageIdentity>();

                for (int i = 0; i < 100; i++)
                {
                    packages.Add(new PackageIdentity(id, NuGetVersion.Parse($"{i + 1}.0.0")));
                }

                await SimpleTestPackageUtility.CreateFolderFeedV3(workingDir, packages.ToArray());

                var tasks = new List <Task>();
                var sem   = new ManualResetEventSlim(false);

                for (int i = 0; i < 10; i++)
                {
                    tasks.Add(Task.Run(() =>
                    {
                        sem.Wait();

                        for (int j = 0; j < 100; j++)
                        {
                            // Fetch
                            var result = target.FindPackagesById(id);

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

                            // Clear
                            for (int k = 0; k < 100; k++)
                            {
                                target.ClearCacheForIds(new[] { id });
                            }
                        }
                    }));
                }

                sem.Set();
                await Task.WhenAll(tasks);

                // Assert
                var results2 = target.FindPackagesById(id);
                Assert.Equal(100, results2.Count());
            }
        }
예제 #5
0
        private async Task InstallPackageAsync(RemoteMatch installItem, NuGetv3LocalRepository userPackageFolder, CancellationToken token)
        {
            var packageIdentity = new PackageIdentity(installItem.Library.Name, installItem.Library.Version);

            // Check if the package has already been installed.
            if (!userPackageFolder.Exists(packageIdentity.Id, packageIdentity.Version))
            {
                var versionFolderPathContext = new VersionFolderPathContext(
                    packageIdentity,
                    _request.PackagesDirectory,
                    _logger,
                    _request.PackageSaveMode,
                    _request.XmlDocFileSaveMode);

                using (var packageDependency = await installItem.Provider.GetPackageDownloaderAsync(
                           packageIdentity,
                           _request.CacheContext,
                           _logger,
                           token))
                {
                    // Install, returns true if the package was actually installed.
                    // Returns false if the package was a noop once the lock
                    // was acquired.
                    var installed = await PackageExtractor.InstallFromSourceAsync(
                        packageDependency,
                        versionFolderPathContext,
                        token);

                    if (installed)
                    {
                        // If the package was added, clear the cache so that the next caller can see it.
                        // Avoid calling this for packages that were not actually installed.
                        userPackageFolder.ClearCacheForIds(new string[] { packageIdentity.Id });
                    }
                }
            }
        }
예제 #6
0
        public async Task <Tuple <bool, List <RestoreTargetGraph>, RuntimeGraph> > TryRestore(LibraryRange projectRange,
                                                                                              IEnumerable <FrameworkRuntimePair> frameworkRuntimePairs,
                                                                                              HashSet <LibraryIdentity> allInstalledPackages,
                                                                                              NuGetv3LocalRepository userPackageFolder,
                                                                                              IReadOnlyList <NuGetv3LocalRepository> fallbackPackageFolders,
                                                                                              RemoteDependencyWalker remoteWalker,
                                                                                              RemoteWalkContext context,
                                                                                              bool forceRuntimeGraphCreation,
                                                                                              CancellationToken token)
        {
            var allRuntimes         = RuntimeGraph.Empty;
            var frameworkTasks      = new List <Task <RestoreTargetGraph> >();
            var graphs              = new List <RestoreTargetGraph>();
            var runtimesByFramework = frameworkRuntimePairs.ToLookup(p => p.Framework, p => p.RuntimeIdentifier);

            foreach (var pair in runtimesByFramework)
            {
                _logger.LogVerbose(string.Format(CultureInfo.CurrentCulture, Strings.Log_RestoringPackages, pair.Key.DotNetFrameworkName));

                frameworkTasks.Add(WalkDependenciesAsync(projectRange,
                                                         pair.Key,
                                                         remoteWalker,
                                                         context,
                                                         token: token));
            }

            var frameworkGraphs = await Task.WhenAll(frameworkTasks);

            graphs.AddRange(frameworkGraphs);

            if (!ResolutionSucceeded(frameworkGraphs))
            {
                return(Tuple.Create(false, graphs, allRuntimes));
            }

            await InstallPackagesAsync(graphs,
                                       _request.PackagesDirectory,
                                       allInstalledPackages,
                                       _request.MaxDegreeOfConcurrency,
                                       token);

            // Clear the in-memory cache for newly installed packages
            userPackageFolder.ClearCacheForIds(allInstalledPackages.Select(package => package.Name));

            var localRepositories = new List <NuGetv3LocalRepository>();

            localRepositories.Add(userPackageFolder);
            localRepositories.AddRange(fallbackPackageFolders);

            // Check if any non-empty RIDs exist before reading the runtime graph (runtime.json).
            // Searching all packages for runtime.json and building the graph can be expensive.
            var hasNonEmptyRIDs = frameworkRuntimePairs.Any(
                tfmRidPair => !string.IsNullOrEmpty(tfmRidPair.RuntimeIdentifier));

            // The runtime graph needs to be created for scenarios with supports, forceRuntimeGraphCreation allows this.
            // Resolve runtime dependencies
            if (hasNonEmptyRIDs || forceRuntimeGraphCreation)
            {
                var runtimeGraphs = new List <RestoreTargetGraph>();

                var runtimeTasks = new List <Task <RestoreTargetGraph[]> >();
                foreach (var graph in graphs)
                {
                    // Get the runtime graph for this specific tfm graph
                    var runtimeGraph = GetRuntimeGraph(graph, localRepositories);
                    var runtimeIds   = runtimesByFramework[graph.Framework];

                    // Merge all runtimes for the output
                    allRuntimes = RuntimeGraph.Merge(allRuntimes, runtimeGraph);

                    runtimeTasks.Add(WalkRuntimeDependenciesAsync(projectRange,
                                                                  graph,
                                                                  runtimeIds.Where(rid => !string.IsNullOrEmpty(rid)),
                                                                  remoteWalker,
                                                                  context,
                                                                  runtimeGraph,
                                                                  token: token));
                }

                foreach (var runtimeSpecificGraph in (await Task.WhenAll(runtimeTasks)).SelectMany(g => g))
                {
                    runtimeGraphs.Add(runtimeSpecificGraph);
                }

                graphs.AddRange(runtimeGraphs);

                if (!ResolutionSucceeded(runtimeGraphs))
                {
                    return(Tuple.Create(false, graphs, allRuntimes));
                }

                // Install runtime-specific packages
                await InstallPackagesAsync(runtimeGraphs,
                                           _request.PackagesDirectory,
                                           allInstalledPackages,
                                           _request.MaxDegreeOfConcurrency,
                                           token);

                // Clear the in-memory cache for newly installed packages
                userPackageFolder.ClearCacheForIds(allInstalledPackages.Select(package => package.Name));
            }

            return(Tuple.Create(true, graphs, allRuntimes));
        }
예제 #7
0
        public async Task <Tuple <bool, List <RestoreTargetGraph>, RuntimeGraph> > TryRestore(LibraryRange projectRange,
                                                                                              IEnumerable <FrameworkRuntimePair> frameworkRuntimePairs,
                                                                                              HashSet <LibraryIdentity> allInstalledPackages,
                                                                                              NuGetv3LocalRepository localRepository,
                                                                                              RemoteDependencyWalker remoteWalker,
                                                                                              RemoteWalkContext context,
                                                                                              bool writeToLockFile,
                                                                                              CancellationToken token)
        {
            var allRuntimes         = RuntimeGraph.Empty;
            var frameworkTasks      = new List <Task <RestoreTargetGraph> >();
            var graphs              = new List <RestoreTargetGraph>();
            var runtimesByFramework = frameworkRuntimePairs.ToLookup(p => p.Framework, p => p.RuntimeIdentifier);

            foreach (var pair in runtimesByFramework)
            {
                _logger.LogVerbose(string.Format(CultureInfo.CurrentCulture, Strings.Log_RestoringPackages, pair.Key.DotNetFrameworkName));

                frameworkTasks.Add(WalkDependenciesAsync(projectRange,
                                                         pair.Key,
                                                         remoteWalker,
                                                         context,
                                                         writeToLockFile: writeToLockFile,
                                                         token: token));
            }

            var frameworkGraphs = await Task.WhenAll(frameworkTasks);

            graphs.AddRange(frameworkGraphs);

            if (!ResolutionSucceeded(frameworkGraphs))
            {
                return(Tuple.Create(false, graphs, allRuntimes));
            }

            await InstallPackagesAsync(graphs,
                                       _request.PackagesDirectory,
                                       allInstalledPackages,
                                       _request.MaxDegreeOfConcurrency,
                                       token);

            // Clear the in-memory cache for newly installed packages
            localRepository.ClearCacheForIds(allInstalledPackages.Select(package => package.Name));

            // Resolve runtime dependencies
            var runtimeGraphs = new List <RestoreTargetGraph>();

            if (runtimesByFramework.Count > 0)
            {
                var runtimeTasks = new List <Task <RestoreTargetGraph[]> >();
                foreach (var graph in graphs)
                {
                    // Get the runtime graph for this specific tfm graph
                    var runtimeGraph = GetRuntimeGraph(graph, localRepository);
                    var runtimeIds   = runtimesByFramework[graph.Framework];

                    // Merge all runtimes for the output
                    allRuntimes = RuntimeGraph.Merge(allRuntimes, runtimeGraph);

                    runtimeTasks.Add(WalkRuntimeDependenciesAsync(projectRange,
                                                                  graph,
                                                                  runtimeIds.Where(rid => !string.IsNullOrEmpty(rid)),
                                                                  remoteWalker,
                                                                  context,
                                                                  localRepository,
                                                                  runtimeGraph,
                                                                  writeToLockFile: writeToLockFile,
                                                                  token: token));
                }

                foreach (var runtimeSpecificGraph in (await Task.WhenAll(runtimeTasks)).SelectMany(g => g))
                {
                    runtimeGraphs.Add(runtimeSpecificGraph);
                }

                graphs.AddRange(runtimeGraphs);

                if (!ResolutionSucceeded(runtimeGraphs))
                {
                    return(Tuple.Create(false, graphs, allRuntimes));
                }

                // Install runtime-specific packages
                await InstallPackagesAsync(runtimeGraphs,
                                           _request.PackagesDirectory,
                                           allInstalledPackages,
                                           _request.MaxDegreeOfConcurrency,
                                           token);

                // Clear the in-memory cache for newly installed packages
                localRepository.ClearCacheForIds(allInstalledPackages.Select(package => package.Name));
            }

            return(Tuple.Create(true, graphs, allRuntimes));
        }