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);
        }
Exemple #2
0
 /// <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;
 }
Exemple #5
0
        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));
        }
Exemple #6
0
        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);
        }
Exemple #7
0
        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);
        }
Exemple #8
0
 private Task<RestoreTargetGraph> WalkDependencies(LibraryRange projectRange, NuGetFramework framework, RemoteDependencyWalker walker, RemoteWalkContext context)
 {
     return WalkDependencies(projectRange, framework, null, RuntimeGraph.Empty, walker, context);
 }
Exemple #9
0
        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;
 }
Exemple #11
0
        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);
        }
Exemple #12
0
 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);
 }