private async Task <RestoreTargetGraph> WalkDependenciesAsync(LibraryRange projectRange,
                                                                      NuGetFramework framework,
                                                                      string runtimeIdentifier,
                                                                      RuntimeGraph runtimeGraph,
                                                                      RemoteDependencyWalker walker,
                                                                      RemoteWalkContext context,
                                                                      CancellationToken token)
        {
            var name   = FrameworkRuntimePair.GetTargetGraphName(framework, runtimeIdentifier);
            var graphs = new List <GraphNode <RemoteResolveResult> >
            {
                await walker.WalkAsync(
                    projectRange,
                    framework,
                    runtimeIdentifier,
                    runtimeGraph,
                    recursive : true)
            };

            // Resolve conflicts
            await _logger.LogAsync(LogLevel.Verbose, string.Format(CultureInfo.CurrentCulture, Strings.Log_ResolvingConflicts, name));

            // Flatten and create the RestoreTargetGraph to hold the packages
            return(RestoreTargetGraph.Create(runtimeGraph, graphs, context, _logger, framework, runtimeIdentifier));
        }
        /// <summary>
        /// Merge all runtime.json found in the flattened graph.
        /// </summary>
        private RuntimeGraph GetRuntimeGraph(RestoreTargetGraph graph, IReadOnlyList <NuGetv3LocalRepository> localRepositories, RuntimeGraph projectRuntimeGraph)
        {
            _logger.LogVerbose(Strings.Log_ScanningForRuntimeJson);
            var runtimeGraph = projectRuntimeGraph ?? RuntimeGraph.Empty;

            // Find runtime.json files using the flattened graph which is unique per id.
            // Using the flattened graph ensures that only accepted packages will be used.
            foreach (var node in graph.Flattened)
            {
                var match = node.Data?.Match;
                if (match == null || match.Library.Type != LibraryType.Package)
                {
                    // runtime.json can only exist in packages
                    continue;
                }

                // Locate the package in the local repository
                var info = NuGetv3LocalRepositoryUtility.GetPackage(localRepositories, match.Library.Name, match.Library.Version);

                // Unresolved packages may not exist.
                if (info != null)
                {
                    var nextGraph = info.Package.RuntimeGraph;
                    if (nextGraph != null)
                    {
                        _logger.LogVerbose(string.Format(CultureInfo.CurrentCulture, Strings.Log_MergingRuntimes, match.Library));
                        runtimeGraph = RuntimeGraph.Merge(runtimeGraph, nextGraph);
                    }
                }
            }

            return(runtimeGraph);
        }
Пример #3
0
        private Task <RestoreTargetGraph[]> WalkRuntimeDependenciesAsync(LibraryRange projectRange,
                                                                         RestoreTargetGraph graph,
                                                                         IEnumerable <string> runtimeIds,
                                                                         RemoteDependencyWalker walker,
                                                                         RemoteWalkContext context,
                                                                         RuntimeGraph runtimes,
                                                                         CancellationToken token)
        {
            var resultGraphs = new List <Task <RestoreTargetGraph> >();

            foreach (var runtimeName in runtimeIds)
            {
                _logger.LogVerbose(string.Format(CultureInfo.CurrentCulture, Strings.Log_RestoringPackages, FrameworkRuntimePair.GetName(graph.Framework, runtimeName)));

                resultGraphs.Add(WalkDependenciesAsync(projectRange,
                                                       graph.Framework,
                                                       runtimeName,
                                                       runtimes,
                                                       walker,
                                                       context,
                                                       token));
            }

            return(Task.WhenAll(resultGraphs));
        }
        private static List <LockFileRuntimeTarget> GetRuntimeTargetLockFileItems(
            RestoreTargetGraph targetGraph,
            LockFileTargetLibrary lockFileLib,
            ContentItemCollection contentItems,
            NuGetFramework framework,
            LibraryIncludeFlags dependencyType,
            LibraryIncludeFlags groupType,
            PatternSet patternSet,
            string assetType)
        {
            var groups = contentItems.FindItemGroups(patternSet).ToList();

            var groupsForFramework = GetContentGroupsForFramework(
                lockFileLib,
                framework,
                groups,
                ManagedCodeConventions.PropertyNames.RuntimeIdentifier);

            var items = GetRuntimeTargetItems(groupsForFramework, assetType);

            if ((dependencyType & groupType) == LibraryIncludeFlags.None)
            {
                ClearIfExists <LockFileRuntimeTarget>(items);
            }

            return(items);
        }
Пример #5
0
        internal static List <List <SelectionCriteria> > CreateOrderedCriteriaSets(RestoreTargetGraph targetGraph, NuGetFramework framework)
        {
            // Create an ordered list of selection criteria. Each will be applied, if the result is empty
            // fallback frameworks from "imports" will be tried.
            // These are only used for framework/RID combinations where content model handles everything.
            // AssetTargetFallback frameworks will provide multiple criteria since all assets need to be
            // evaluated before selecting the TFM to use.
            var orderedCriteriaSets = new List <List <SelectionCriteria> >(1);

            var assetTargetFallback = framework as AssetTargetFallbackFramework;

            if (assetTargetFallback != null)
            {
                // Add the root project framework first.
                orderedCriteriaSets.Add(CreateCriteria(targetGraph, assetTargetFallback.RootFramework));

                // Add all fallbacks in order.
                orderedCriteriaSets.AddRange(assetTargetFallback.Fallback.Select(e => CreateCriteria(targetGraph, e)));
            }
            else
            {
                // Add the current framework.
                orderedCriteriaSets.Add(CreateCriteria(targetGraph, framework));
            }

            return(orderedCriteriaSets);
        }
Пример #6
0
        private RuntimeGraph GetRuntimeGraph(RestoreTargetGraph graph, IReadOnlyList <NuGetv3LocalRepository> localRepositories)
        {
            // TODO: Caching!
            RuntimeGraph runtimeGraph;

            if (_request.RuntimeGraphCache.TryGetValue(graph.Framework, out runtimeGraph))
            {
                return(runtimeGraph);
            }

            _logger.LogVerbose(Strings.Log_ScanningForRuntimeJson);
            runtimeGraph = RuntimeGraph.Empty;

            // maintain visited nodes to avoid duplicate runtime graph for the same node
            var visitedNodes = new HashSet <string>(StringComparer.OrdinalIgnoreCase);

            graph.Graphs.ForEach(node =>
            {
                var match = node?.Item?.Data?.Match;
                if (match == null)
                {
                    return;
                }

                // Ignore runtime.json from rejected nodes
                if (node.Disposition == Disposition.Rejected)
                {
                    return;
                }

                // ignore the same node again
                if (!visitedNodes.Add(match.Library.Name))
                {
                    return;
                }

                // runtime.json can only exist in packages
                if (match.Library.Type != LibraryType.Package)
                {
                    return;
                }

                // Locate the package in the local repository
                var info = NuGetv3LocalRepositoryUtility.GetPackage(localRepositories, match.Library.Name, match.Library.Version);

                if (info != null)
                {
                    var package   = info.Package;
                    var nextGraph = LoadRuntimeGraph(package);
                    if (nextGraph != null)
                    {
                        _logger.LogVerbose(string.Format(CultureInfo.CurrentCulture, Strings.Log_MergingRuntimes, match.Library));
                        runtimeGraph = RuntimeGraph.Merge(runtimeGraph, nextGraph);
                    }
                }
            });
            _request.RuntimeGraphCache[graph.Framework] = runtimeGraph;
            return(runtimeGraph);
        }
Пример #7
0
        public static LockFileTargetLibrary CreateLockFileTargetLibrary(
            LockFileLibrary library,
            LocalPackageInfo package,
            RestoreTargetGraph targetGraph,
            LibraryIncludeFlags dependencyType,
            NuGetFramework targetFrameworkOverride,
            IEnumerable <LibraryDependency> dependencies)
        {
            LockFileTargetLibrary lockFileLib = null;

            var framework         = targetFrameworkOverride ?? targetGraph.Framework;
            var runtimeIdentifier = targetGraph.RuntimeIdentifier;

            // Read files from package
            var files        = GetPackageFiles(library, package);
            var contentItems = new ContentItemCollection();

            contentItems.Load(files);

            // This will throw an appropriate error if the nuspec is missing
            var nuspec = package.Nuspec;

            // Create fallback criteria, this will always be one or more.
            var orderedCriteriaSets = CreateOrderedCriteriaSets(targetGraph, framework);

            for (var i = 0; i < orderedCriteriaSets.Count; i++)
            {
                // Create a new library each time to avoid
                // assets being added from other criteria.
                lockFileLib = new LockFileTargetLibrary()
                {
                    Name    = package.Id,
                    Version = package.Version,
                    Type    = LibraryType.Package
                };

                // Populate assets
                AddAssets(library, package, targetGraph, dependencyType, lockFileLib, framework, runtimeIdentifier, files, contentItems, nuspec, orderedCriteriaSets[i]);

                // Check if compatile assets were found.
                // If no compatible assets were found and this is the last check
                // continue on with what was given, this will fail in the normal
                // compat verification.
                if (CompatibilityChecker.HasCompatibleAssets(lockFileLib))
                {
                    // Stop when compatible assets are found.
                    break;
                }
            }

            // Add dependencies
            AddDependencies(dependencies, lockFileLib, framework, nuspec);

            // Exclude items
            ExcludeItems(lockFileLib, dependencyType);

            return(lockFileLib);
        }
Пример #8
0
 /// <summary>
 /// Create a library for a project.
 /// </summary>
 public static LockFileTargetLibrary CreateLockFileTargetProject(
     GraphItem <RemoteResolveResult> graphItem,
     LibraryIdentity library,
     LibraryIncludeFlags dependencyType,
     RestoreTargetGraph targetGraph,
     ProjectStyle rootProjectStyle)
 {
     return(CreateLockFileTargetProject(graphItem, library, dependencyType, targetGraph, rootProjectStyle, maccatalystFallback: null));
 }
Пример #9
0
 public static LockFileTargetLibrary CreateLockFileTargetLibrary(
     LockFileLibrary library,
     LocalPackageInfo package,
     RestoreTargetGraph targetGraph,
     LibraryIncludeFlags dependencyType,
     NuGetFramework targetFrameworkOverride,
     IEnumerable <LibraryDependency> dependencies,
     LockFileBuilderCache cache)
 {
     return(CreateLockFileTargetLibrary(libraryDependency: null, library, package, targetGraph, dependencyType, targetFrameworkOverride, dependencies, cache));
 }
Пример #10
0
 /// <summary>
 /// Format a graph name with an optional RID.
 /// </summary>
 public static string FormatGraphName(RestoreTargetGraph graph)
 {
     if (string.IsNullOrEmpty(graph.RuntimeIdentifier))
     {
         return($"({graph.Framework.DotNetFrameworkName})");
     }
     else
     {
         return($"({graph.Framework.DotNetFrameworkName} RuntimeIdentifier: {graph.RuntimeIdentifier})");
     }
 }
Пример #11
0
        private CompatibilityData GetCompatibilityData(RestoreTargetGraph graph, LibraryIdentity libraryId, PackageSpec packageSpec)
        {
            // Use data from the current lock file if it exists.
            LockFileTargetLibrary targetLibrary = null;
            var target = _lockFile.Targets.FirstOrDefault(t => Equals(t.TargetFramework, graph.Framework) && string.Equals(t.RuntimeIdentifier, graph.RuntimeIdentifier, StringComparison.Ordinal));

            if (target != null)
            {
                targetLibrary = target.Libraries
                                .FirstOrDefault(t => t.Name.Equals(libraryId.Name, StringComparison.OrdinalIgnoreCase) && t.Version.Equals(libraryId.Version));
            }

            IEnumerable <string> files = null;
            var lockFileLibrary        = _lockFile.Libraries
                                         .FirstOrDefault(l => l.Name.Equals(libraryId.Name, StringComparison.OrdinalIgnoreCase) && l.Version.Equals(libraryId.Version));

            if (lockFileLibrary != null)
            {
                files = lockFileLibrary.Files;
            }

            if (files == null || targetLibrary == null)
            {
                // We need to generate some of the data. We'll need the local package info to do that
                var packageInfo = NuGetv3LocalRepositoryUtility.GetPackage(
                    _localRepositories,
                    libraryId.Name,
                    libraryId.Version);

                if (packageInfo == null)
                {
                    return(null);
                }

                // Collect the file list if necessary
                if (files == null)
                {
                    files = packageInfo.Package.Files;
                }

                // Generate the target library if necessary
                if (targetLibrary == null)
                {
                    targetLibrary = LockFileUtils.CreateLockFileTargetLibrary(
                        library: null,
                        package: packageInfo.Package,
                        targetGraph: graph,
                        dependencyType: LibraryIncludeFlags.All);
                }
            }

            return(new CompatibilityData(files, targetLibrary, packageSpec));
        }
Пример #12
0
        /// <summary>
        /// Get ordered selection criteria.
        /// </summary>
        public List <List <SelectionCriteria> > GetSelectionCriteria(RestoreTargetGraph graph, NuGetFramework framework)
        {
            // Criteria are unique on graph and framework override.
            var key = new CriteriaKey(graph.TargetGraphName, framework);

            if (!_criteriaSets.TryGetValue(key, out var criteria))
            {
                criteria = LockFileUtils.CreateOrderedCriteriaSets(graph, framework);
                _criteriaSets.Add(key, criteria);
            }

            return(criteria);
        }
Пример #13
0
        /// <summary>
        /// Runtime targets
        /// These are applied only to non-RID target graphs.
        /// They are not used for compatibility checks.
        /// </summary>
        private static void AddRuntimeTargets(
            RestoreTargetGraph targetGraph,
            LibraryIncludeFlags dependencyType,
            LockFileTargetLibrary lockFileLib,
            NuGetFramework framework,
            string runtimeIdentifier,
            ContentItemCollection contentItems,
            MaccatalystFallback maccatalystFallback)
        {
            if (string.IsNullOrEmpty(runtimeIdentifier))
            {
                // Runtime targets contain all the runtime specific assets
                // that could be contained in the runtime specific target graphs.
                // These items are contained in a flat list and have additional properties
                // for the RID and lock file section the assembly would belong to.
                var runtimeTargetItems = new List <LockFileRuntimeTarget>();

                // Runtime
                runtimeTargetItems.AddRange(GetRuntimeTargetLockFileItems(
                                                contentItems,
                                                framework,
                                                dependencyType,
                                                LibraryIncludeFlags.Runtime,
                                                targetGraph.Conventions.Patterns.RuntimeAssemblies,
                                                "runtime",
                                                maccatalystFallback));

                // Resource
                runtimeTargetItems.AddRange(GetRuntimeTargetLockFileItems(
                                                contentItems,
                                                framework,
                                                dependencyType,
                                                LibraryIncludeFlags.Runtime,
                                                targetGraph.Conventions.Patterns.ResourceAssemblies,
                                                "resource",
                                                maccatalystFallback));

                // Native
                runtimeTargetItems.AddRange(GetRuntimeTargetLockFileItems(
                                                contentItems,
                                                framework,
                                                dependencyType,
                                                LibraryIncludeFlags.Native,
                                                targetGraph.Conventions.Patterns.NativeLibraries,
                                                "native",
                                                maccatalystFallback));

                lockFileLib.RuntimeTargets = runtimeTargetItems;
            }
        }
Пример #14
0
 public static LockFileTargetLibrary CreateLockFileTargetLibrary(
     LockFileLibrary library,
     LocalPackageInfo package,
     RestoreTargetGraph targetGraph,
     LibraryIncludeFlags dependencyType)
 {
     return(CreateLockFileTargetLibrary(
                library,
                package,
                targetGraph,
                dependencyType: dependencyType,
                targetFrameworkOverride: null,
                dependencies: null));
 }
        internal static Dictionary <string, LibraryIncludeFlags> FlattenDependencyTypes(
            Dictionary <RestoreTargetGraph, Dictionary <string, LibraryIncludeFlags> > includeFlagGraphs,
            PackageSpec project,
            RestoreTargetGraph graph)
        {
            Dictionary <string, LibraryIncludeFlags> flattenedFlags;

            if (!includeFlagGraphs.TryGetValue(graph, out flattenedFlags))
            {
                flattenedFlags = FlattenDependencyTypes(graph, project);
                includeFlagGraphs.Add(graph, flattenedFlags);
            }

            return(flattenedFlags);
        }
        private static IEnumerable <NuGetFramework> GetPackageFrameworks(
            CompatibilityData compatibilityData,
            RestoreTargetGraph graph)
        {
            var available = new HashSet <NuGetFramework>();

            var contentItems = new ContentItemCollection();

            contentItems.Load(compatibilityData.Files);

            var patterns = new[]
            {
                graph.Conventions.Patterns.ResourceAssemblies,
                graph.Conventions.Patterns.CompileRefAssemblies,
                graph.Conventions.Patterns.RuntimeAssemblies,
                graph.Conventions.Patterns.EmbedAssemblies,
                graph.Conventions.Patterns.ContentFiles
            };

            List <ContentItemGroup> itemGroups = new();

            foreach (var pattern in patterns)
            {
                itemGroups.Clear();
                contentItems.PopulateItemGroups(pattern, itemGroups);
                foreach (var group in itemGroups)
                {
                    // lib/net45/subfolder/a.dll will be returned as a group with zero items since sub
                    // folders are not allowed. Completely empty groups are not compatible, a group with
                    // _._ would contain _._ as an item.
                    if (group.Items.Count > 0)
                    {
                        group.Properties.TryGetValue(ManagedCodeConventions.PropertyNames.RuntimeIdentifier, out var ridObj);
                        group.Properties.TryGetValue(ManagedCodeConventions.PropertyNames.TargetFrameworkMoniker, out var tfmObj);

                        var tfm = tfmObj as NuGetFramework;

                        // RID specific items should be ignored here since they are only used in the runtime assembly check
                        if (ridObj == null && tfm?.IsSpecificFramework == true)
                        {
                            available.Add(tfm);
                        }
                    }
                }
            }

            return(available);
        }
Пример #17
0
        private static void AddContentFiles(RestoreTargetGraph targetGraph, LockFileTargetLibrary lockFileLib, NuGetFramework framework, ContentItemCollection contentItems, NuspecReader nuspec)
        {
            // content v2 items
            var contentFileGroups = contentItems.FindItemGroups(targetGraph.Conventions.Patterns.ContentFiles);

            // Multiple groups can match the same framework, find all of them
            var contentFileGroupsForFramework = ContentFileUtils.GetContentGroupsForFramework(
                lockFileLib,
                framework,
                contentFileGroups);

            lockFileLib.ContentFiles = ContentFileUtils.GetContentFileGroup(
                framework,
                nuspec,
                contentFileGroupsForFramework);
        }
Пример #18
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.Walk(
                projectRange,
                framework,
                runtimeIdentifier,
                runtimeGraph);

            // Resolve conflicts
            _log.LogVerbose($"Resolving Conflicts for {framework}");
            bool inConflict = !graph.TryResolveConflicts();

            // Flatten and create the RestoreTargetGraph to hold the packages
            return(RestoreTargetGraph.Create(inConflict, framework, runtimeIdentifier, runtimeGraph, graph, context, _loggerFactory));
        }
Пример #19
0
 public static LockFileTargetLibrary CreateLockFileTargetLibrary(
     LockFileLibrary library,
     LocalPackageInfo package,
     RestoreTargetGraph targetGraph,
     LibraryIncludeFlags dependencyType)
 {
     return(CreateLockFileTargetLibrary(
                aliases: null,
                library,
                package,
                targetGraph,
                dependencyType: dependencyType,
                targetFrameworkOverride: null,
                dependencies: null,
                cache: new LockFileBuilderCache(),
                maccatalystFallback: null));
 }
Пример #20
0
        private static void AddToolsAssets(LockFileLibrary library,
                                           LocalPackageInfo package,
                                           RestoreTargetGraph targetGraph,
                                           LibraryIncludeFlags dependencyType,
                                           LockFileTargetLibrary lockFileLib,
                                           NuGetFramework framework,
                                           string runtimeIdentifier,
                                           ContentItemCollection contentItems,
                                           NuspecReader nuspec,
                                           IReadOnlyList <SelectionCriteria> orderedCriteria)
        {
            var toolsGroup = GetLockFileItems(
                orderedCriteria,
                contentItems,
                targetGraph.Conventions.Patterns.ToolsAssemblies);

            lockFileLib.ToolsAssemblies.AddRange(toolsGroup);
        }
 public static LockFileTargetLibrary CreateLockFileTargetLibrary(
     LockFileLibrary library,
     LocalPackageInfo package,
     RestoreTargetGraph targetGraph,
     VersionFolderPathResolver defaultPackagePathResolver,
     string correctedPackageName,
     LibraryIncludeFlags dependencyType)
 {
     return(CreateLockFileTargetLibrary(
                library,
                package,
                targetGraph,
                defaultPackagePathResolver,
                correctedPackageName,
                dependencyType: dependencyType,
                targetFrameworkOverride: null,
                dependencies: null));
 }
Пример #22
0
        private RuntimeGraph GetRuntimeGraph(RestoreTargetGraph graph, IReadOnlyList <NuGetv3LocalRepository> localRepositories)
        {
            // TODO: Caching!
            RuntimeGraph runtimeGraph;

            if (_request.RuntimeGraphCache.TryGetValue(graph.Framework, out runtimeGraph))
            {
                return(runtimeGraph);
            }

            _logger.LogVerbose(Strings.Log_ScanningForRuntimeJson);
            runtimeGraph = RuntimeGraph.Empty;
            graph.Graphs.ForEach(node =>
            {
                var match = node?.Item?.Data?.Match;
                if (match == null)
                {
                    return;
                }

                // Ignore runtime.json from rejected nodes
                if (node.Disposition == Disposition.Rejected)
                {
                    return;
                }

                // Locate the package in the local repository
                var info = NuGetv3LocalRepositoryUtility.GetPackage(localRepositories, match.Library.Name, match.Library.Version);

                if (info != null)
                {
                    var package   = info.Package;
                    var nextGraph = LoadRuntimeGraph(package);
                    if (nextGraph != null)
                    {
                        _logger.LogVerbose(string.Format(CultureInfo.CurrentCulture, Strings.Log_MergingRuntimes, match.Library));
                        runtimeGraph = RuntimeGraph.Merge(runtimeGraph, nextGraph);
                    }
                }
            });
            _request.RuntimeGraphCache[graph.Framework] = runtimeGraph;
            return(runtimeGraph);
        }
Пример #23
0
        private static void AddMSBuildAssets(
            LockFileLibrary library,
            RestoreTargetGraph targetGraph,
            LockFileTargetLibrary lockFileLib,
            IReadOnlyList <SelectionCriteria> orderedCriteria,
            ContentItemCollection contentItems,
            MaccatalystFallback maccatalystFallback)
        {
            // Build Transitive
            var btGroup = GetLockFileItems(
                orderedCriteria,
                contentItems,
                maccatalystFallback,
                targetGraph.Conventions.Patterns.MSBuildTransitiveFiles);

            var filteredBTGroup = GetBuildItemsForPackageId(btGroup, library.Name);

            lockFileLib.Build.AddRange(filteredBTGroup);

            // Build
            var buildGroup = GetLockFileItems(
                orderedCriteria,
                contentItems,
                maccatalystFallback,
                targetGraph.Conventions.Patterns.MSBuildFiles);

            // filter any build asset already being added as part of build transitive
            var filteredBuildGroup = GetBuildItemsForPackageId(buildGroup, library.Name).
                                     Where(buildItem => !filteredBTGroup.Any(
                                               btItem => Path.GetFileName(btItem.Path).Equals(Path.GetFileName(buildItem.Path), StringComparison.OrdinalIgnoreCase)));

            lockFileLib.Build.AddRange(filteredBuildGroup);

            // Build multi targeting
            var buildMultiTargetingGroup = GetLockFileItems(
                orderedCriteria,
                contentItems,
                maccatalystFallback,
                targetGraph.Conventions.Patterns.MSBuildMultiTargetingFiles);

            lockFileLib.BuildMultiTargeting.AddRange(GetBuildItemsForPackageId(buildMultiTargetingGroup, library.Name));
        }
Пример #24
0
        /// <summary>
        /// Creates an ordered list of selection criteria to use. This supports fallback frameworks.
        /// </summary>
        private static IReadOnlyList <SelectionCriteria> CreateCriteria(
            RestoreTargetGraph targetGraph,
            NuGetFramework framework)
        {
            var managedCriteria = new List <SelectionCriteria>(1);

            var fallbackFramework = framework as FallbackFramework;

            // Avoid fallback criteria if this is not a fallback framework,
            // or if AssetTargetFallback is used. For AssetTargetFallback
            // the fallback frameworks will be checked later.
            if (fallbackFramework == null)
            {
                var standardCriteria = targetGraph.Conventions.Criteria.ForFrameworkAndRuntime(
                    framework,
                    targetGraph.RuntimeIdentifier);

                managedCriteria.Add(standardCriteria);
            }
            else
            {
                // Add the project framework
                var primaryFramework = NuGetFramework.Parse(fallbackFramework.DotNetFrameworkName);
                var primaryCriteria  = targetGraph.Conventions.Criteria.ForFrameworkAndRuntime(
                    primaryFramework,
                    targetGraph.RuntimeIdentifier);

                managedCriteria.Add(primaryCriteria);

                // Add each fallback framework in order
                foreach (var fallback in fallbackFramework.Fallback)
                {
                    var fallbackCriteria = targetGraph.Conventions.Criteria.ForFrameworkAndRuntime(
                        fallback,
                        targetGraph.RuntimeIdentifier);

                    managedCriteria.Add(fallbackCriteria);
                }
            }

            return(managedCriteria);
        }
Пример #25
0
        private async Task <RestoreTargetGraph> WalkDependenciesAsync(LibraryRange projectRange,
                                                                      NuGetFramework framework,
                                                                      string runtimeIdentifier,
                                                                      RuntimeGraph runtimeGraph,
                                                                      RemoteDependencyWalker walker,
                                                                      RemoteWalkContext context,
                                                                      CancellationToken token)
        {
            var name   = FrameworkRuntimePair.GetName(framework, runtimeIdentifier);
            var graphs = new List <GraphNode <RemoteResolveResult> >();

            graphs.Add(await walker.WalkAsync(
                           projectRange,
                           framework,
                           runtimeIdentifier,
                           runtimeGraph,
                           recursive: true));

            // Resolve conflicts
            _logger.LogVerbose(string.Format(CultureInfo.CurrentCulture, Strings.Log_ResolvingConflicts, name));

            // Flatten and create the RestoreTargetGraph to hold the packages
            var result = RestoreTargetGraph.Create(runtimeGraph, graphs, context, _logger, framework, runtimeIdentifier);

            // Check if the dependencies got bumped up
            if (_request.ExistingLockFile == null)
            {
                // No lock file, so check dependencies
                CheckDependencies(result, _request.Project.Dependencies);

                var fxInfo = _request.Project.GetTargetFramework(framework);
                if (fxInfo != null)
                {
                    CheckDependencies(result, fxInfo.Dependencies);
                }
            }

            return(result);
        }
Пример #26
0
        private static List <NuGetFramework> GetPackageFrameworks(
            CompatibilityData compatibilityData,
            RestoreTargetGraph graph)
        {
            var available = new HashSet <NuGetFramework>();

            var contentItems = new ContentItemCollection();

            contentItems.Load(compatibilityData.Files);

            var patterns = new[]
            {
                graph.Conventions.Patterns.ResourceAssemblies,
                graph.Conventions.Patterns.CompileRefAssemblies,
                graph.Conventions.Patterns.RuntimeAssemblies,
                graph.Conventions.Patterns.ContentFiles
            };

            foreach (var pattern in patterns)
            {
                foreach (var group in contentItems.FindItemGroups(pattern))
                {
                    object tfmObj = null;
                    object ridObj = null;
                    group.Properties.TryGetValue(ManagedCodeConventions.PropertyNames.RuntimeIdentifier, out ridObj);
                    group.Properties.TryGetValue(ManagedCodeConventions.PropertyNames.TargetFrameworkMoniker, out tfmObj);

                    NuGetFramework tfm = tfmObj as NuGetFramework;

                    // RID specific items should be ignored here since they are only used in the runtime assem check
                    if (ridObj == null && tfm?.IsSpecificFramework == true)
                    {
                        available.Add(tfm);
                    }
                }
            }

            return(available.ToList());
        }
Пример #27
0
 private void CheckDependencies(RestoreTargetGraph result, IEnumerable <LibraryDependency> dependencies)
 {
     foreach (var dependency in dependencies)
     {
         // Ignore floating or version-less (project) dependencies
         // Avoid warnings for non-packages
         if (dependency.LibraryRange.TypeConstraintAllows(LibraryDependencyTarget.Package) &&
             dependency.LibraryRange.VersionRange != null && !dependency.LibraryRange.VersionRange.IsFloating)
         {
             var match = result.Flattened.FirstOrDefault(g => g.Key.Name.Equals(dependency.LibraryRange.Name));
             if (match != null &&
                 LibraryType.Package == match.Key.Type &&
                 match.Key.Version > dependency.LibraryRange.VersionRange.MinVersion)
             {
                 _logger.LogWarning(string.Format(CultureInfo.CurrentCulture, Strings.Log_DependencyBumpedUp,
                                                  dependency.LibraryRange.Name,
                                                  dependency.LibraryRange.VersionRange.PrettyPrint(),
                                                  match.Key.Name,
                                                  match.Key.Version));
             }
         }
     }
 }
        internal static Dictionary <string, LibraryIncludeFlags> FlattenDependencyTypes(
            RestoreTargetGraph targetGraph,
            PackageSpec spec)
        {
            var result = new Dictionary <string, LibraryIncludeFlags>(StringComparer.OrdinalIgnoreCase);

            // Walk dependencies
            FlattenDependencyTypesUnified(targetGraph, result);

            // Override flags for direct dependencies
            var directDependencies = spec.Dependencies.ToList();

            // Add dependencies defined under the framework node
            var specFramework = spec.GetTargetFramework(targetGraph.Framework);

            if (specFramework?.Dependencies != null)
            {
                directDependencies.AddRange(specFramework.Dependencies);
            }

            // Override the flags for direct dependencies. This lets the
            // user take control when needed.
            foreach (var dependency in directDependencies)
            {
                if (result.ContainsKey(dependency.Name))
                {
                    result[dependency.Name] = dependency.IncludeType;
                }
                else
                {
                    result.Add(dependency.Name, dependency.IncludeType);
                }
            }

            return(result);
        }
Пример #29
0
        public static LockFileTargetLibrary CreateLockFileTargetLibrary(
            LockFileLibrary library,
            LocalPackageInfo package,
            RestoreTargetGraph targetGraph,
            LibraryIncludeFlags dependencyType,
            NuGetFramework targetFrameworkOverride,
            IEnumerable <LibraryDependency> dependencies)
        {
            var lockFileLib = new LockFileTargetLibrary();

            var framework         = targetFrameworkOverride ?? targetGraph.Framework;
            var runtimeIdentifier = targetGraph.RuntimeIdentifier;

            lockFileLib.Name    = package.Id;
            lockFileLib.Version = package.Version;
            lockFileLib.Type    = LibraryType.Package;

            IList <string>   files;
            var              contentItems    = new ContentItemCollection();
            HashSet <string> referenceFilter = null;

            // If the previous LockFileLibrary was given, use that to find the file list. Otherwise read the nupkg.
            if (library == null)
            {
                using (var packageReader = new PackageFolderReader(package.ExpandedPath))
                {
                    if (Path.DirectorySeparatorChar != LockFile.DirectorySeparatorChar)
                    {
                        files = packageReader
                                .GetFiles()
                                .Select(p => p.Replace(Path.DirectorySeparatorChar, LockFile.DirectorySeparatorChar))
                                .ToList();
                    }
                    else
                    {
                        files = packageReader
                                .GetFiles()
                                .ToList();
                    }
                }
            }
            else
            {
                if (Path.DirectorySeparatorChar != LockFile.DirectorySeparatorChar)
                {
                    files = library.Files.Select(p => p.Replace(Path.DirectorySeparatorChar, LockFile.DirectorySeparatorChar)).ToList();
                }
                else
                {
                    files = library.Files;
                }
            }

            contentItems.Load(files);

            // This will throw an appropriate error if the nuspec is missing
            var nuspec = package.Nuspec;

            if (dependencies == null)
            {
                var dependencySet = nuspec
                                    .GetDependencyGroups()
                                    .GetNearest(framework);

                if (dependencySet != null)
                {
                    var set = dependencySet.Packages;

                    if (set != null)
                    {
                        lockFileLib.Dependencies = set.ToList();
                    }
                }
            }
            else
            {
                // Filter the dependency set down to packages and projects.
                // Framework references will not be displayed
                lockFileLib.Dependencies = dependencies
                                           .Where(ld => ld.LibraryRange.TypeConstraintAllowsAnyOf(LibraryDependencyTarget.PackageProjectExternal))
                                           .Select(ld => new PackageDependency(ld.Name, ld.LibraryRange.VersionRange))
                                           .ToList();
            }

            var referenceSet = nuspec.GetReferenceGroups().GetNearest(framework);

            if (referenceSet != null)
            {
                referenceFilter = new HashSet <string>(referenceSet.Items, StringComparer.OrdinalIgnoreCase);
            }

            // Exclude framework references for package based frameworks.
            if (!framework.IsPackageBased)
            {
                var frameworkAssemblies = nuspec.GetFrameworkReferenceGroups().GetNearest(framework);
                if (frameworkAssemblies != null)
                {
                    foreach (var assemblyReference in frameworkAssemblies.Items)
                    {
                        lockFileLib.FrameworkAssemblies.Add(assemblyReference);
                    }
                }
            }

            // Create an ordered list of selection criteria. Each will be applied, if the result is empty
            // fallback frameworks from "imports" will be tried.
            // These are only used for framework/RID combinations where content model handles everything.
            var orderedCriteria = CreateCriteria(targetGraph, framework);

            // Compile
            var compileGroup = GetLockFileItems(
                orderedCriteria,
                contentItems,
                targetGraph.Conventions.Patterns.CompileAssemblies,
                targetGraph.Conventions.Patterns.RuntimeAssemblies);

            lockFileLib.CompileTimeAssemblies.AddRange(compileGroup);

            // Runtime
            var runtimeGroup = GetLockFileItems(
                orderedCriteria,
                contentItems,
                targetGraph.Conventions.Patterns.RuntimeAssemblies);

            lockFileLib.RuntimeAssemblies.AddRange(runtimeGroup);

            // Resources
            var resourceGroup = GetLockFileItems(
                orderedCriteria,
                contentItems,
                targetGraph.Conventions.Patterns.ResourceAssemblies);

            lockFileLib.ResourceAssemblies.AddRange(resourceGroup);

            // Native
            var nativeGroup = GetLockFileItems(
                orderedCriteria,
                contentItems,
                targetGraph.Conventions.Patterns.NativeLibraries);

            lockFileLib.NativeLibraries.AddRange(nativeGroup);

            // content v2 items
            var contentFileGroups = contentItems.FindItemGroups(targetGraph.Conventions.Patterns.ContentFiles);

            // Multiple groups can match the same framework, find all of them
            var contentFileGroupsForFramework = ContentFileUtils.GetContentGroupsForFramework(
                lockFileLib,
                framework,
                contentFileGroups);

            lockFileLib.ContentFiles = ContentFileUtils.GetContentFileGroup(
                framework,
                nuspec,
                contentFileGroupsForFramework);

            // Runtime targets
            // These are applied only to non-RID target graphs.
            // They are not used for compatibility checks.
            if (string.IsNullOrEmpty(runtimeIdentifier))
            {
                // Runtime targets contain all the runtime specific assets
                // that could be contained in the runtime specific target graphs.
                // These items are contained in a flat list and have additional properties
                // for the RID and lock file section the assembly would belong to.
                var runtimeTargetItems = new List <LockFileRuntimeTarget>();

                // Runtime
                runtimeTargetItems.AddRange(GetRuntimeTargetLockFileItems(
                                                contentItems,
                                                framework,
                                                dependencyType,
                                                LibraryIncludeFlags.Runtime,
                                                targetGraph.Conventions.Patterns.RuntimeAssemblies,
                                                "runtime"));

                // Resource
                runtimeTargetItems.AddRange(GetRuntimeTargetLockFileItems(
                                                contentItems,
                                                framework,
                                                dependencyType,
                                                LibraryIncludeFlags.Runtime,
                                                targetGraph.Conventions.Patterns.ResourceAssemblies,
                                                "resource"));

                // Native
                runtimeTargetItems.AddRange(GetRuntimeTargetLockFileItems(
                                                contentItems,
                                                framework,
                                                dependencyType,
                                                LibraryIncludeFlags.Native,
                                                targetGraph.Conventions.Patterns.NativeLibraries,
                                                "native"));

                lockFileLib.RuntimeTargets = runtimeTargetItems;
            }

            // COMPAT: Support lib/contract so older packages can be consumed
            var contractPath = "lib/contract/" + package.Id + ".dll";
            var hasContract  = files.Any(path => path == contractPath);
            var hasLib       = lockFileLib.RuntimeAssemblies.Any();

            if (hasContract &&
                hasLib &&
                !framework.IsDesktop())
            {
                lockFileLib.CompileTimeAssemblies.Clear();
                lockFileLib.CompileTimeAssemblies.Add(new LockFileItem(contractPath));
            }

            // Apply filters from the <references> node in the nuspec
            if (referenceFilter != null)
            {
                // Remove anything that starts with "lib/" and is NOT specified in the reference filter.
                // runtimes/* is unaffected (it doesn't start with lib/)
                lockFileLib.RuntimeAssemblies     = lockFileLib.RuntimeAssemblies.Where(p => !p.Path.StartsWith("lib/") || referenceFilter.Contains(Path.GetFileName(p.Path))).ToList();
                lockFileLib.CompileTimeAssemblies = lockFileLib.CompileTimeAssemblies.Where(p => !p.Path.StartsWith("lib/") || referenceFilter.Contains(Path.GetFileName(p.Path))).ToList();
            }

            // Exclude items
            if ((dependencyType & LibraryIncludeFlags.Runtime) == LibraryIncludeFlags.None)
            {
                ClearIfExists(lockFileLib.RuntimeAssemblies);
                lockFileLib.FrameworkAssemblies.Clear();
                lockFileLib.ResourceAssemblies.Clear();
            }

            if ((dependencyType & LibraryIncludeFlags.Compile) == LibraryIncludeFlags.None)
            {
                ClearIfExists(lockFileLib.CompileTimeAssemblies);
            }

            if ((dependencyType & LibraryIncludeFlags.Native) == LibraryIncludeFlags.None)
            {
                ClearIfExists(lockFileLib.NativeLibraries);
            }

            if ((dependencyType & LibraryIncludeFlags.ContentFiles) == LibraryIncludeFlags.None &&
                GroupHasNonEmptyItems(lockFileLib.ContentFiles))
            {
                // Empty lock file items still need lock file properties for language, action, and output.
                lockFileLib.ContentFiles.Clear();
                lockFileLib.ContentFiles.Add(ContentFileUtils.CreateEmptyItem());
            }

            return(lockFileLib);
        }
Пример #30
0
        private LockFileTargetLibrary CreateLockFileTargetLibrary(LocalPackageInfo package, RestoreTargetGraph targetGraph, DefaultPackagePathResolver defaultPackagePathResolver, string correctedPackageName)
        {
            var lockFileLib = new LockFileTargetLibrary();

            var framework = targetGraph.Framework;
            var runtimeIdentifier = targetGraph.RuntimeIdentifier;

            // package.Id is read from nuspec and it might be in wrong casing.
            // correctedPackageName should be the package name used by dependency graph and
            // it has the correct casing that runtime needs during dependency resolution.
            lockFileLib.Name = correctedPackageName ?? package.Id;
            lockFileLib.Version = package.Version;

            IList<string> files;
            var contentItems = new ContentItemCollection();
            HashSet<string> referenceFilter = null;
            using (var nupkgStream = File.OpenRead(package.ZipPath))
            {
                var packageReader = new PackageReader(nupkgStream);
                files = packageReader.GetFiles().Select(p => p.Replace(Path.DirectorySeparatorChar, '/')).ToList();

                contentItems.Load(files);

                var dependencySet = packageReader.GetPackageDependencies().GetNearest(framework);
                if (dependencySet != null)
                {
                    var set = dependencySet.Packages;

                    if (set != null)
                    {
                        lockFileLib.Dependencies = set.ToList();
                    }
                }

                var referenceSet = packageReader.GetReferenceItems().GetNearest(framework);
                if (referenceSet != null)
                {
                    referenceFilter = new HashSet<string>(referenceSet.Items, StringComparer.OrdinalIgnoreCase);
                }

                // TODO: Remove this when we do #596
                // ASP.NET Core isn't compatible with generic PCL profiles
                if (!string.Equals(framework.Framework, FrameworkConstants.FrameworkIdentifiers.AspNetCore, StringComparison.OrdinalIgnoreCase)
                    &&
                    !string.Equals(framework.Framework, FrameworkConstants.FrameworkIdentifiers.DnxCore, StringComparison.OrdinalIgnoreCase))
                {
                    var frameworkAssemblies = packageReader.GetFrameworkItems().GetNearest(framework);
                    if (frameworkAssemblies != null)
                    {
                        foreach (var assemblyReference in frameworkAssemblies.Items)
                        {
                            lockFileLib.FrameworkAssemblies.Add(assemblyReference);
                        }
                    }
                }
            }

            var nativeCriteria = targetGraph.Conventions.Criteria.ForRuntime(targetGraph.RuntimeIdentifier);
            var managedCriteria = targetGraph.Conventions.Criteria.ForFrameworkAndRuntime(framework, targetGraph.RuntimeIdentifier);

            var compileGroup = contentItems.FindBestItemGroup(managedCriteria, targetGraph.Conventions.Patterns.CompileAssemblies, targetGraph.Conventions.Patterns.RuntimeAssemblies);

            if (compileGroup != null)
            {
                lockFileLib.CompileTimeAssemblies = compileGroup.Items.Select(t => new LockFileItem(t.Path)).ToList();
            }

            var runtimeGroup = contentItems.FindBestItemGroup(managedCriteria, targetGraph.Conventions.Patterns.RuntimeAssemblies);
            if (runtimeGroup != null)
            {
                lockFileLib.RuntimeAssemblies = runtimeGroup.Items.Select(p => new LockFileItem(p.Path)).ToList();
            }

            var resourceGroup = contentItems.FindBestItemGroup(managedCriteria, targetGraph.Conventions.Patterns.ResourceAssemblies);
            if (resourceGroup != null)
            {
                lockFileLib.ResourceAssemblies = resourceGroup.Items.Select(ToResourceLockFileItem).ToList();
            }

            var nativeGroup = contentItems.FindBestItemGroup(nativeCriteria, targetGraph.Conventions.Patterns.NativeLibraries);
            if (nativeGroup != null)
            {
                lockFileLib.NativeLibraries = nativeGroup.Items.Select(p => new LockFileItem(p.Path)).ToList();
            }

            // COMPAT: Support lib/contract so older packages can be consumed
            var contractPath = "lib/contract/" + package.Id + ".dll";
            var hasContract = files.Any(path => path == contractPath);
            var hasLib = lockFileLib.RuntimeAssemblies.Any();

            if (hasContract
                && hasLib
                && !framework.IsDesktop())
            {
                lockFileLib.CompileTimeAssemblies.Clear();
                lockFileLib.CompileTimeAssemblies.Add(new LockFileItem(contractPath));
            }

            // Apply filters from the <references> node in the nuspec
            if (referenceFilter != null)
            {
                // Remove anything that starts with "lib/" and is NOT specified in the reference filter.
                // runtimes/* is unaffected (it doesn't start with lib/)
                lockFileLib.RuntimeAssemblies = lockFileLib.RuntimeAssemblies.Where(p => !p.Path.StartsWith("lib/") || referenceFilter.Contains(p.Path)).ToList();
                lockFileLib.CompileTimeAssemblies = lockFileLib.CompileTimeAssemblies.Where(p => !p.Path.StartsWith("lib/") || referenceFilter.Contains(p.Path)).ToList();
            }

            return lockFileLib;
        }
Пример #31
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);
        }
Пример #32
0
        internal async Task <CompatibilityCheckResult> CheckAsync(
            RestoreTargetGraph graph,
            Dictionary <string, LibraryIncludeFlags> includeFlags,
            PackageSpec packageSpec)
        {
            // The Compatibility Check is designed to alert the user to cases where packages are not behaving as they would
            // expect, due to compatibility issues.
            //
            // During this check, we scan all packages for a given restore graph and check the following conditions
            // (using an example TxM 'foo' and an example Runtime ID 'bar'):
            //
            // * If any package provides a "ref/foo/Thingy.dll", there MUST be a matching "lib/foo/Thingy.dll" or
            //   "runtimes/bar/lib/foo/Thingy.dll" provided by a package in the graph.
            // * All packages that contain Managed Assemblies must provide assemblies for 'foo'. If a package
            //   contains any of 'ref/' folders, 'lib/' folders, or framework assemblies, it must provide at least
            //   one of those for the 'foo' framework. Otherwise, the package is intending to provide managed assemblies
            //   but it does not support the target platform. If a package contains only 'content/', 'build/', 'tools/' or
            //   other NuGet convention folders, it is exempt from this check. Thus, content-only packages are always considered
            //   compatible, regardless of if they actually provide useful content.
            //
            // It is up to callers to invoke the compatibility check on the graphs they wish to check, but the general behavior in
            // the restore command is to invoke a compatibility check for each of:
            //
            // * The Targets (TxMs) defined in the project.json, with no Runtimes
            // * All combinations of TxMs and Runtimes defined in the project.json
            // * Additional (TxMs, Runtime) pairs defined by the "supports" mechanism in project.json
            var runtimeAssemblies = new HashSet <string>(StringComparer.OrdinalIgnoreCase);
            var compileAssemblies = new Dictionary <string, LibraryIdentity>(StringComparer.OrdinalIgnoreCase);
            var issues            = new List <CompatibilityIssue>();

            if (packageSpec.RestoreMetadata?.ProjectStyle == ProjectStyle.DotnetToolReference)
            {
                // Autoreferenced packages are allowed. Currently they're using Microsoft.NET.Platforms as an auto-ref package
                if (packageSpec.GetAllPackageDependencies().Where(e => !e.AutoReferenced).Count() != 1)
                {
                    // Create issue
                    var issue = CompatibilityIssue.IncompatibleProjectType(
                        new PackageIdentity(packageSpec.Name, packageSpec.Version));

                    issues.Add(issue);
                    await _log.LogAsync(GetErrorMessage(NuGetLogCode.NU1211, issue, graph));
                }
            }

            // Verify framework assets also as part of runtime assets validation.
            foreach (var node in graph.Flattened)
            {
                await _log.LogAsync(LogLevel.Debug, string.Format(CultureInfo.CurrentCulture, Strings.Log_CheckingPackageCompatibility, node.Key.Name, node.Key.Version, graph.Name));

                // Check project compatibility
                if (node.Key.Type == LibraryType.Project)
                {
                    // Get the full library
                    var localMatch = node.Data?.Match as LocalMatch;
                    if (localMatch == null || !IsProjectFrameworkCompatible(localMatch.LocalLibrary))
                    {
                        var available = new List <NuGetFramework>();

                        // If the project info is available find all available frameworks
                        if (localMatch?.LocalLibrary != null)
                        {
                            available = GetProjectFrameworks(localMatch.LocalLibrary);
                        }

                        // Create issue
                        var issue = CompatibilityIssue.IncompatibleProject(
                            new PackageIdentity(node.Key.Name, node.Key.Version),
                            graph.Framework,
                            graph.RuntimeIdentifier,
                            available);

                        issues.Add(issue);
                        await _log.LogAsync(GetErrorMessage(NuGetLogCode.NU1201, issue, graph));
                    }

                    // Skip further checks on projects
                    continue;
                }

                // Find the include/exclude flags for this package
                LibraryIncludeFlags packageIncludeFlags;
                if (!includeFlags.TryGetValue(node.Key.Name, out packageIncludeFlags))
                {
                    packageIncludeFlags = LibraryIncludeFlags.All;
                }

                // If the package has compile and runtime assets excluded the compatibility check
                // is not needed. Packages with no ref or lib entries are considered
                // compatible in IsCompatible.
                if ((packageIncludeFlags &
                     (LibraryIncludeFlags.Compile
                      | LibraryIncludeFlags.Runtime)) == LibraryIncludeFlags.None)
                {
                    continue;
                }

                var compatibilityData = GetCompatibilityData(graph, node.Key, packageSpec);
                if (compatibilityData == null)
                {
                    continue;
                }

                if (!IsPackageCompatible(compatibilityData))
                {
                    var available = GetPackageFrameworks(compatibilityData, graph);

                    var issue = CompatibilityIssue.IncompatiblePackage(
                        new PackageIdentity(node.Key.Name, node.Key.Version),
                        graph.Framework,
                        graph.RuntimeIdentifier,
                        available);

                    issues.Add(issue);
                    await _log.LogAsync(GetErrorMessage(NuGetLogCode.NU1202, issue, graph));
                }

                await VerifyDotnetToolCompatibilityChecks(compatibilityData, node, graph, issues);

                // Check for matching ref/libs if we're checking a runtime-specific graph
                var targetLibrary = compatibilityData.TargetLibrary;
                if (_validateRuntimeAssets && !string.IsNullOrEmpty(graph.RuntimeIdentifier))
                {
                    // Skip runtime checks for packages that have runtime references excluded,
                    // this allows compile only packages that do not have runtimes for the
                    // graph RID to be used.
                    if ((packageIncludeFlags & LibraryIncludeFlags.Runtime) == LibraryIncludeFlags.Runtime)
                    {
                        // Scan the package for ref assemblies
                        foreach (var compile in targetLibrary.CompileTimeAssemblies
                                 .Where(p => Path.GetExtension(p.Path)
                                        .Equals(".dll", StringComparison.OrdinalIgnoreCase)))
                        {
                            var name = Path.GetFileNameWithoutExtension(compile.Path);

                            // If we haven't already started tracking this compile-time assembly, AND there isn't already a runtime-loadable version
                            if (!compileAssemblies.ContainsKey(name) && !runtimeAssemblies.Contains(name))
                            {
                                // Track this assembly as potentially compile-time-only
                                compileAssemblies.Add(name, node.Key);
                            }
                        }

                        // Match up runtime assemblies
                        foreach (var runtime in targetLibrary.RuntimeAssemblies
                                 .Where(p => Path.GetExtension(p.Path)
                                        .Equals(".dll", StringComparison.OrdinalIgnoreCase)))
                        {
                            var name = Path.GetFileNameWithoutExtension(runtime.Path);

                            // If there was a compile-time-only assembly under this name...
                            if (compileAssemblies.ContainsKey(name))
                            {
                                // Remove it, we've found a matching runtime ref
                                compileAssemblies.Remove(name);
                            }

                            // Track this assembly as having a runtime assembly
                            runtimeAssemblies.Add(name);

                            // Fix for NuGet/Home#752 - Consider ".ni.dll" (native image/ngen) files matches for ref/ assemblies
                            if (name.EndsWith(".ni", StringComparison.OrdinalIgnoreCase))
                            {
                                var withoutNi = name.Substring(0, name.Length - 3);

                                if (compileAssemblies.ContainsKey(withoutNi))
                                {
                                    compileAssemblies.Remove(withoutNi);
                                }

                                runtimeAssemblies.Add(withoutNi);
                            }
                        }
                    }
                }
            }

            // Generate errors for un-matched reference assemblies, if we're checking a runtime-specific graph
            if (_validateRuntimeAssets && !string.IsNullOrEmpty(graph.RuntimeIdentifier))
            {
                foreach (var compile in compileAssemblies)
                {
                    var issue = CompatibilityIssue.ReferenceAssemblyNotImplemented(
                        compile.Key,
                        new PackageIdentity(compile.Value.Name, compile.Value.Version),
                        graph.Framework,
                        graph.RuntimeIdentifier);

                    issues.Add(issue);
                    await _log.LogAsync(GetErrorMessage(NuGetLogCode.NU1203, issue, graph));
                }
            }

            return(new CompatibilityCheckResult(graph, issues));
        }