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