public static async Task <GraphItem <RemoteResolveResult> > FindLibraryEntryAsync( LibraryRange libraryRange, NuGetFramework framework, string runtimeIdentifier, GraphEdge <RemoteResolveResult> outerEdge, RemoteWalkContext context, CancellationToken cancellationToken) { GraphItem <RemoteResolveResult> graphItem = null; var currentCacheContext = context.CacheContext; // Try up to two times to get the package. The second // retry will refresh the cache if a package is listed // but fails to download. This can happen if the feed prunes // the package. for (var i = 0; i < 2 && graphItem == null; i++) { var match = await FindLibraryMatchAsync( libraryRange, framework, runtimeIdentifier, outerEdge, context.RemoteLibraryProviders, context.LocalLibraryProviders, context.ProjectLibraryProviders, context.LockFileLibraries, currentCacheContext, context.Logger, cancellationToken); if (match == null) { return(CreateUnresolvedMatch(libraryRange)); } try { graphItem = await CreateGraphItemAsync(match, framework, currentCacheContext, context.Logger, cancellationToken); } catch (InvalidCacheProtocolException) when(i == 0) { // 1st failure, invalidate the cache and try again. // Clear the on disk and memory caches during the next request. currentCacheContext = currentCacheContext.WithRefreshCacheTrue(); } catch (PackageNotFoundProtocolException ex) when(match.Provider.IsHttp && match.Provider.Source != null) { // 2nd failure, the feed is likely corrupt or removing packages too fast to keep up with. var message = string.Format(CultureInfo.CurrentCulture, Strings.Error_PackageNotFoundWhenExpected, match.Provider.Source, ex.PackageIdentity.ToString()); throw new FatalProtocolException(message, ex); } } return(graphItem); }
/// <summary> /// Resolves the library from the given sources. Note that it does not download the package. /// </summary> /// <param name="cache">Cache of requests per library</param> /// <param name="libraryRange">The library requested</param> /// <param name="remoteWalkContext">remote Providers (all sources, including file sources)</param> /// <param name="cancellationToken">cancellation token</param> /// <returns>The requested range and remote match.</returns> public static Task <Tuple <LibraryRange, RemoteMatch> > FindPackageLibraryMatchCachedAsync( ConcurrentDictionary <LibraryRange, Task <Tuple <LibraryRange, RemoteMatch> > > cache, LibraryRange libraryRange, RemoteWalkContext remoteWalkContext, CancellationToken cancellationToken) { return(cache.GetOrAdd(libraryRange, (cacheKey) => ResolvePackageLibraryMatchAsync(libraryRange, remoteWalkContext, cancellationToken))); }
public static Task <GraphItem <RemoteResolveResult> > FindLibraryCachedAsync( ConcurrentDictionary <LibraryRangeCacheKey, Task <GraphItem <RemoteResolveResult> > > cache, LibraryRange libraryRange, NuGetFramework framework, string runtimeIdentifier, RemoteWalkContext context, CancellationToken cancellationToken) { var key = new LibraryRangeCacheKey(libraryRange, framework); return(cache.GetOrAdd(key, (cacheKey) => FindLibraryEntryAsync(cacheKey.LibraryRange, framework, runtimeIdentifier, context, cancellationToken))); }
public RemoteDependencyWalker(RemoteWalkContext context) { _context = context; }
private static async Task <Tuple <LibraryRange, RemoteMatch> > ResolvePackageLibraryMatchAsync(LibraryRange libraryRange, RemoteWalkContext remoteWalkContext, CancellationToken cancellationToken) { IList <IRemoteDependencyProvider> remoteDependencyProviders = remoteWalkContext.FilterDependencyProvidersForLibrary(libraryRange); if (libraryRange.TypeConstraintAllows(LibraryDependencyTarget.Package)) { LogIfPackageSourceMappingIsEnabled(libraryRange.Name, remoteWalkContext, remoteDependencyProviders); } var match = await FindPackageLibraryMatchAsync(libraryRange, NuGetFramework.AnyFramework, remoteDependencyProviders, remoteWalkContext.LocalLibraryProviders, remoteWalkContext.CacheContext, remoteWalkContext.Logger, cancellationToken); if (match == null) { match = CreateUnresolvedMatch(libraryRange); } return(new Tuple <LibraryRange, RemoteMatch>(libraryRange, match)); }
private async Task<RestoreTargetGraph> WalkDependencies(LibraryRange projectRange, NuGetFramework framework, string runtimeIdentifier, RuntimeGraph runtimeGraph, RemoteDependencyWalker walker, RemoteWalkContext context) { _log.LogInformation($"Restoring packages for {framework}"); var graph = await walker.WalkAsync( projectRange, framework, runtimeIdentifier, runtimeGraph); // Resolve conflicts _log.LogVerbose($"Resolving Conflicts for {framework}"); var inConflict = !graph.TryResolveConflicts(); // Flatten and create the RestoreTargetGraph to hold the packages return RestoreTargetGraph.Create(inConflict, framework, runtimeIdentifier, runtimeGraph, graph, context, _log); }
private Task<RestoreTargetGraph[]> WalkRuntimeDependencies(LibraryRange projectRange, RestoreTargetGraph graph, RuntimeGraph projectRuntimeGraph, RemoteDependencyWalker walker, RemoteWalkContext context, NuGetv3LocalRepository localRepository) { // Load runtime specs _log.LogVerbose("Scanning packages for runtime.json files..."); var runtimeGraph = projectRuntimeGraph; graph.Graph.ForEach(node => { var match = node?.Item?.Data?.Match; if (match == null) { return; } // Locate the package in the local repository var package = localRepository.FindPackagesById(match.Library.Name).FirstOrDefault(p => p.Version == match.Library.Version); if (package != null) { var nextGraph = LoadRuntimeGraph(package); if (nextGraph != null) { _log.LogVerbose($"Merging in runtimes defined in {match.Library}"); runtimeGraph = RuntimeGraph.Merge(runtimeGraph, nextGraph); } } }); var resultGraphs = new List<Task<RestoreTargetGraph>>(); foreach (var runtimeName in projectRuntimeGraph.Runtimes.Keys) { _log.LogInformation($"Restoring packages for {graph.Framework} on {runtimeName}"); resultGraphs.Add(WalkDependencies(projectRange, graph.Framework, runtimeName, runtimeGraph, walker, context)); } return Task.WhenAll(resultGraphs); }
private Task<RestoreTargetGraph> WalkDependencies(LibraryRange projectRange, NuGetFramework framework, RemoteDependencyWalker walker, RemoteWalkContext context) { return WalkDependencies(projectRange, framework, null, RuntimeGraph.Empty, walker, context); }
public async Task<RestoreResult> ExecuteAsync(RestoreRequest request) { if (request.Project.TargetFrameworks.Count == 0) { _log.LogError("The project does not specify any target frameworks!"); return new RestoreResult(success: false, restoreGraphs: Enumerable.Empty<RestoreTargetGraph>()); } var projectLockFilePath = string.IsNullOrEmpty(request.LockFilePath) ? Path.Combine(request.Project.BaseDirectory, LockFileFormat.LockFileName) : request.LockFilePath; _log.LogInformation($"Restoring packages for '{request.Project.FilePath}'"); _log.LogWarning("TODO: Read and use lock file"); // Load repositories var projectResolver = new PackageSpecResolver(request.Project); var nugetRepository = Repository.Factory.GetCoreV3(request.PackagesDirectory); var context = new RemoteWalkContext(); ExternalProjectReference exterenalProjectReference = null; if (request.ExternalProjects.Any()) { exterenalProjectReference = new ExternalProjectReference( request.Project.Name, request.Project.FilePath, request.ExternalProjects.Select(p => p.Name)); } context.ProjectLibraryProviders.Add( new LocalDependencyProvider( new PackageSpecReferenceDependencyProvider(projectResolver, exterenalProjectReference))); if (request.ExternalProjects != null) { context.ProjectLibraryProviders.Add( new LocalDependencyProvider( new ExternalProjectReferenceDependencyProvider(request.ExternalProjects))); } context.LocalLibraryProviders.Add( new SourceRepositoryDependencyProvider(nugetRepository, _log)); foreach (var provider in request.Sources.Select(s => CreateProviderFromSource(s, request.NoCache))) { context.RemoteLibraryProviders.Add(provider); } var remoteWalker = new RemoteDependencyWalker(context); var projectRange = new LibraryRange() { Name = request.Project.Name, VersionRange = new VersionRange(request.Project.Version), TypeConstraint = LibraryTypes.Project }; // Resolve dependency graphs var frameworks = request.Project.TargetFrameworks.Select(f => f.FrameworkName).ToList(); var graphs = new List<RestoreTargetGraph>(); var frameworkTasks = new List<Task<RestoreTargetGraph>>(); foreach (var framework in frameworks) { frameworkTasks.Add(WalkDependencies(projectRange, framework, remoteWalker, context)); } graphs.AddRange(await Task.WhenAll(frameworkTasks)); if (graphs.Any(g => g.InConflict)) { _log.LogError("Failed to resolve conflicts"); return new RestoreResult(success: false, restoreGraphs: graphs); } // Install the runtime-agnostic packages var allInstalledPackages = new HashSet<LibraryIdentity>(); var localRepository = new NuGetv3LocalRepository(request.PackagesDirectory, checkPackageIdCase: false); await InstallPackages(graphs, request.PackagesDirectory, allInstalledPackages, request.MaxDegreeOfConcurrency); // Resolve runtime dependencies var runtimeGraphs = new List<RestoreTargetGraph>(); if (request.Project.RuntimeGraph.Runtimes.Count > 0) { var runtimeTasks = new List<Task<RestoreTargetGraph[]>>(); foreach (var graph in graphs) { runtimeTasks.Add(WalkRuntimeDependencies(projectRange, graph, request.Project.RuntimeGraph, remoteWalker, context, localRepository)); } foreach (var runtimeSpecificGraphs in await Task.WhenAll(runtimeTasks)) { runtimeGraphs.AddRange(runtimeSpecificGraphs); } graphs.AddRange(runtimeGraphs); if (runtimeGraphs.Any(g => g.InConflict)) { _log.LogError("Failed to resolve conflicts"); return new RestoreResult(success: false, restoreGraphs: graphs); } // Install runtime-specific packages await InstallPackages(runtimeGraphs, request.PackagesDirectory, allInstalledPackages, request.MaxDegreeOfConcurrency); } else { _log.LogVerbose("Skipping runtime dependency walk, no runtimes defined in project.json"); } // Build the lock file var repository = new NuGetv3LocalRepository(request.PackagesDirectory, checkPackageIdCase: false); var lockFile = CreateLockFile(request.Project, graphs, repository); var lockFileFormat = new LockFileFormat(); lockFileFormat.Write(projectLockFilePath, lockFile); // Generate Targets/Props files WriteTargetsAndProps(request.Project, graphs, repository); return new RestoreResult(true, graphs, lockFile); }
public RemoteDependencyWalker(RemoteWalkContext context) { _context = context; }
public static RestoreTargetGraph Create( bool inConflict, NuGetFramework framework, string runtimeIdentifier, RuntimeGraph runtimeGraph, GraphNode<RemoteResolveResult> graph, RemoteWalkContext context, ILogger log) { var install = new HashSet<RemoteMatch>(); var flattened = new HashSet<GraphItem<RemoteResolveResult>>(); var unresolved = new HashSet<LibraryRange>(); graph.ForEach(node => { if (node == null || node.Key == null || node.Disposition == Disposition.Rejected) { return; } if (node.Item == null || node.Item.Data.Match == null) { if (node.Key.TypeConstraint != LibraryTypes.Reference && node.Key.VersionRange != null) { unresolved.Add(node.Key); } return; } if (!string.Equals(node.Item.Data.Match.Library.Name, node.Key.Name, StringComparison.Ordinal)) { // Fix casing of the library name to be installed node.Item.Data.Match.Library.Name = node.Key.Name; } // If the package came from a remote library provider, it needs to be installed locally var isRemote = context.RemoteLibraryProviders.Contains(node.Item.Data.Match.Provider); if (isRemote) { install.Add(node.Item.Data.Match); } flattened.Add(node.Item); }); return new RestoreTargetGraph( inConflict, framework, runtimeIdentifier, runtimeGraph, graph, install, flattened, unresolved); }
public static RestoreTargetGraph Create(bool inConflict, NuGetFramework framework, GraphNode<RemoteResolveResult> graph, RemoteWalkContext context, ILogger logger) { return Create(inConflict, framework, null, RuntimeGraph.Empty, graph, context, logger); }