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); }
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()); } }
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 }); } } } }
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)); }
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)); }