public void ContentFiles_Empty() { // Arrange var conventions = new ManagedCodeConventions( new RuntimeGraph( new List <CompatibilityProfile>() { new CompatibilityProfile("net46.app") })); var criteria = conventions.Criteria.ForFramework(NuGetFramework.Parse("net46")); var collection = new ContentItemCollection(); collection.Load(new string[] { // empty }); // Act var contentFileGroups = collection.FindItemGroups(conventions.Patterns.ContentFiles); // Assert Assert.Equal(0, contentFileGroups.Count()); }
public void ContentFiles_InvalidPaths() { // Arrange var conventions = new ManagedCodeConventions( new RuntimeGraph( new List <CompatibilityProfile>() { new CompatibilityProfile("net46.app") })); var criteria = conventions.Criteria.ForFramework(NuGetFramework.Parse("net46")); var collection = new ContentItemCollection(); collection.Load(new string[] { "contentFiles/any/config1.xml", "contentFiles/in.valid/net45/config2.xml", "contentFiles/any/config3.xml", "contentFiles/config4.xml", "contentFiles", "contentFiles/+/uap10.0.0/config6.xml" }); // Act var contentFileGroups = collection.FindItemGroups(conventions.Patterns.ContentFiles); // Assert Assert.Equal(0, contentFileGroups.Count()); }
private static List <LockFileRuntimeTarget> GetRuntimeTargetLockFileItems( ContentItemCollection contentItems, NuGetFramework framework, LibraryIncludeFlags dependencyType, LibraryIncludeFlags groupType, PatternSet patternSet, string assetType, MaccatalystFallback maccatalystFallback) { var groups = contentItems.FindItemGroups(patternSet).ToList(); var groupsForFramework = GetContentGroupsForFramework( framework, groups, ManagedCodeConventions.PropertyNames.RuntimeIdentifier, maccatalystFallback); var items = GetRuntimeTargetItems(groupsForFramework, assetType); if ((dependencyType & groupType) == LibraryIncludeFlags.None) { ClearIfExists <LockFileRuntimeTarget>(items); } return(items); }
public void ContentModel_ContentFilesAnyMapsToAny() { // Arrange var conventions = new ManagedCodeConventions( new RuntimeGraph( new List <CompatibilityProfile>() { new CompatibilityProfile("net46.app") })); var collection = new ContentItemCollection(); collection.Load(new string[] { "contentFiles/any/any/a.txt", }); // Act var groups = collection.FindItemGroups(conventions.Patterns.ContentFiles) .OrderBy(group => ((NuGetFramework)group.Properties["tfm"]).GetShortFolderName()) .ToList(); // Assert Assert.Equal(1, groups.Count); Assert.Equal(NuGetFramework.AnyFramework, (NuGetFramework)groups[0].Properties["tfm"]); }
public void ContentModel_BuildNoFilesAtRootNoAnyGroup() { // Arrange var conventions = new ManagedCodeConventions( new RuntimeGraph( new List <CompatibilityProfile>() { new CompatibilityProfile("net46.app") })); var collection = new ContentItemCollection(); collection.Load(new string[] { "build/net46/packageA.targets", "build/net45/packageA.targets", "build/net35/packageA.targets", "build/net20/packageA.targets", "build/uap10.0/packageA.targets", }); // Act var groups = collection.FindItemGroups(conventions.Patterns.MSBuildFiles) .Select(group => ((NuGetFramework)group.Properties["tfm"])) .ToList(); // Assert Assert.Equal(0, groups.Count(framework => framework == NuGetFramework.AnyFramework)); }
public void ContentModel_BuildAnyFolderTreatedAsDotNet() { // Arrange var conventions = new ManagedCodeConventions( new RuntimeGraph( new List <CompatibilityProfile>() { new CompatibilityProfile("net46.app") })); var collection = new ContentItemCollection(); collection.Load(new string[] { "build/any/packageA.targets" }); // Act var framework = collection.FindItemGroups(conventions.Patterns.MSBuildFiles) .Select(group => ((NuGetFramework)group.Properties["tfm"])) .Single(); // Assert Assert.Equal(".NETPlatform", framework.Framework); }
public void ContentModel_BuildRootFolderRandomFiles() { // Arrange var conventions = new ManagedCodeConventions( new RuntimeGraph( new List <CompatibilityProfile>() { new CompatibilityProfile("net46.app") })); var collection = new ContentItemCollection(); collection.Load(new string[] { "build/config.xml", "build/net45/task.dll", "build/net45/task.targets", "build/net45/task.props", }); // Act var groups = collection.FindItemGroups(conventions.Patterns.MSBuildFiles); // Assert Assert.Equal(1, groups.Count()); Assert.Equal(NuGetFramework.Parse("net45"), groups.First().Properties["tfm"] as NuGetFramework); }
public void ContentModel_ResourcesAnyMapsToDotnet() { // Arrange var conventions = new ManagedCodeConventions( new RuntimeGraph( new List <CompatibilityProfile>() { new CompatibilityProfile("net46.app") })); var collection = new ContentItemCollection(); collection.Load(new string[] { "lib/any/en-us/a.resources.dll", }); // Act var groups = collection.FindItemGroups(conventions.Patterns.ResourceAssemblies) .OrderBy(group => ((NuGetFramework)group.Properties["tfm"]).GetShortFolderName()) .ToList(); // Assert Assert.Equal(1, groups.Count); Assert.Equal(FrameworkConstants.CommonFrameworks.DotNet, (NuGetFramework)groups[0].Properties["tfm"]); }
public void ContentModel_AnyTFMDefaultsToAnyandAnyRIDisAnyRID() { // Arrange var conventions = new ManagedCodeConventions( new RuntimeGraph( new List <CompatibilityProfile>() { new CompatibilityProfile("net46.app") })); var collection = new ContentItemCollection(); var rid = "any"; collection.Load(new string[] { $"tools/any/{rid}/a.dll", }); // Act var groups = collection.FindItemGroups(conventions.Patterns.ToolsAssemblies) .ToList(); // Assert Assert.Equal(1, groups.Count); Assert.Equal(NuGetFramework.AnyFramework, (NuGetFramework)groups.First().Properties["tfm"]); Assert.Equal(rid, groups.First().Properties["rid"]); }
public void ContentModel_NoTFMAndRuntimeIdentifierNoMatch() { // Arrange var conventions = new ManagedCodeConventions( new RuntimeGraph( new List <CompatibilityProfile>() { new CompatibilityProfile("net46.app") })); var collection = new ContentItemCollection(); collection.Load(new string[] { "tools/a.dll", }); // Act var groups = collection.FindItemGroups(conventions.Patterns.ToolsAssemblies) .Select(group => ((NuGetFramework)group.Properties["tfm"])) .ToList(); // Assert Assert.Equal(0, groups.Count); }
private static HashSet <FrameworkRuntimePair> GetAvailableFrameworkRuntimePairs(CompatibilityData compatibilityData, RestoreTargetGraph graph) { var available = new HashSet <FrameworkRuntimePair>(); var contentItems = new ContentItemCollection(); contentItems.Load(compatibilityData.Files); if (compatibilityData.TargetLibrary.PackageType.Contains(PackageType.DotnetTool)) { foreach (var group in contentItems.FindItemGroups(graph.Conventions.Patterns.ToolsAssemblies)) { group.Properties.TryGetValue(ManagedCodeConventions.PropertyNames.RuntimeIdentifier, out var ridObj); group.Properties.TryGetValue(ManagedCodeConventions.PropertyNames.TargetFrameworkMoniker, out var tfmObj); var tfm = tfmObj as NuGetFramework; var rid = ridObj as string; if (tfm?.IsSpecificFramework == true) { available.Add(new FrameworkRuntimePair(tfm, rid)); } } } return(available); }
public void ContentModel_LibRootAndTFM() { // Arrange var conventions = new ManagedCodeConventions( new RuntimeGraph( new List <CompatibilityProfile>() { new CompatibilityProfile("net46.app") })); var collection = new ContentItemCollection(); collection.Load(new string[] { "lib/net46/a.dll", "lib/a.dll", }); // Act var groups = collection.FindItemGroups(conventions.Patterns.RuntimeAssemblies) .OrderBy(group => ((NuGetFramework)group.Properties["tfm"]).GetShortFolderName()) .ToList(); // Assert Assert.Equal(2, groups.Count); Assert.Equal(NuGetFramework.Parse("net"), groups[0].Properties["tfm"]); Assert.Equal(NuGetFramework.Parse("net46"), groups[1].Properties["tfm"]); }
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 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.EmbedAssemblies, graph.Conventions.Patterns.ContentFiles }; foreach (var pattern in patterns) { foreach (var group in contentItems.FindItemGroups(pattern)) { // 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.ToList()); }
public void ContentFiles_BasicContentModelCheck() { // Arrange var conventions = new ManagedCodeConventions( new RuntimeGraph( new List <CompatibilityProfile>() { new CompatibilityProfile("net46.app") })); var criteria = conventions.Criteria.ForFramework(NuGetFramework.Parse("net46")); var collection = new ContentItemCollection(); collection.Load(new string[] { "contentFiles/any/net45/config1.xml", "contentFiles/cs/net45/config2.xml", "contentFiles/vb/net45/config3.xml", "contentFiles/any/uap/config4.xml", "contentFiles/cs/uap/config5.xml", "contentFiles/vb/uap/config6.xml" }); // Act var contentFileGroups = collection.FindItemGroups(conventions.Patterns.ContentFiles); // Assert Assert.Equal(6, contentFileGroups.Count()); Assert.Equal("any|cs|vb", string.Join("|", contentFileGroups.Select(group => group.Properties[ManagedCodeConventions.PropertyNames.CodeLanguage]) .Distinct() .OrderBy(s => s))); Assert.Equal("net45|uap", string.Join("|", contentFileGroups.Select(group => group.Properties[ManagedCodeConventions.PropertyNames.TargetFrameworkMoniker] as NuGetFramework) .Select(f => f.GetShortFolderName()) .Distinct() .OrderBy(s => s))); }
public void ContentModel_BuildNoFilesAtRoot() { // Arrange var conventions = new ManagedCodeConventions( new RuntimeGraph( new List <CompatibilityProfile>() { new CompatibilityProfile("net46.app") })); var collection = new ContentItemCollection(); collection.Load(new string[] { "build/net46/packageA.targets", "build/net45/packageA.targets", "build/net35/packageA.targets", "build/net20/packageA.targets", "build/uap10.0/packageA.targets", }); // Act var groups = collection.FindItemGroups(conventions.Patterns.MSBuildFiles) .OrderBy(group => ((NuGetFramework)group.Properties["tfm"]).GetShortFolderName()) .ToList(); // Assert Assert.Equal(5, groups.Count()); Assert.Equal(NuGetFramework.Parse("net20"), groups[0].Properties["tfm"] as NuGetFramework); Assert.Equal(NuGetFramework.Parse("net35"), groups[1].Properties["tfm"] as NuGetFramework); Assert.Equal(NuGetFramework.Parse("net45"), groups[2].Properties["tfm"] as NuGetFramework); Assert.Equal(NuGetFramework.Parse("net46"), groups[3].Properties["tfm"] as NuGetFramework); Assert.Equal(NuGetFramework.Parse("uap10.0"), groups[4].Properties["tfm"] as NuGetFramework); Assert.Equal("build/net20/packageA.targets", groups[0].Items.Single().Path); Assert.Equal("build/net35/packageA.targets", groups[1].Items.Single().Path); Assert.Equal("build/net45/packageA.targets", groups[2].Items.Single().Path); Assert.Equal("build/net46/packageA.targets", groups[3].Items.Single().Path); Assert.Equal("build/uap10.0/packageA.targets", groups[4].Items.Single().Path); }
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()); }
public void ContentFiles_BasicContentModelSubFolders() { // Arrange var conventions = new ManagedCodeConventions( new RuntimeGraph( new List <CompatibilityProfile>() { new CompatibilityProfile("net46.app") })); var criteria = conventions.Criteria.ForFramework(NuGetFramework.Parse("net46")); var collection = new ContentItemCollection(); collection.Load(new string[] { "contentFiles/any/net45/config1.xml", "contentFiles/any/net45/folder/a/b/c/config2.xml", }); // Act var contentFileGroups = collection.FindItemGroups(conventions.Patterns.ContentFiles); // Assert Assert.Equal(1, contentFileGroups.Count()); Assert.Equal(2, contentFileGroups.Single().Items.Count); Assert.Equal("any", contentFileGroups.Select(group => (string)group.Properties[ManagedCodeConventions.PropertyNames.CodeLanguage]) .Single()); Assert.Equal("contentFiles/any/net45/config1.xml|contentFiles/any/net45/folder/a/b/c/config2.xml", string.Join("|", contentFileGroups.SelectMany(group => group.Items) .Select(item => item.Path) .OrderBy(s => s))); }
public void ContentModel_Net46TFMAndAnyRIDisAnyRID() { // Arrange var conventions = new ManagedCodeConventions( new RuntimeGraph( new List <CompatibilityProfile>() { new CompatibilityProfile("net46.app") })); var collection = new ContentItemCollection(); var rid = "any"; collection.Load(new string[] { $"tools/net46/{rid}/a.dll", }); // Arrange var criteria = conventions.Criteria.ForFrameworkAndRuntime(NuGetFramework.Parse("net46"), rid); // Act var group = collection.FindBestItemGroup(criteria, conventions.Patterns.ToolsAssemblies); // Assert Assert.Equal(FrameworkConstants.CommonFrameworks.Net46, (NuGetFramework)group.Properties["tfm"]); Assert.Equal(rid, group.Properties["rid"]); // Act var groups = collection.FindItemGroups(conventions.Patterns.ToolsAssemblies) .ToList(); // Assert Assert.Equal(1, groups.Count); Assert.Equal(FrameworkConstants.CommonFrameworks.Net46, (NuGetFramework)groups.First().Properties["tfm"]); Assert.Equal(rid, groups.First().Properties["rid"]); }
internal static IEnumerable <ContentItemGroup> GetContentForPattern(ContentItemCollection collection, PatternSet pattern) { return(collection.FindItemGroups(pattern)); }
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); }
public NugetRepositoryEntry ResolveGroups(LocalPackageSourceInfo localPackageSourceInfo) { var collection = new ContentItemCollection(); collection.Load(localPackageSourceInfo.Package.Files); var allPackageDependencyGroups = localPackageSourceInfo.Package.Nuspec.GetDependencyGroups().ToArray(); var frameworkReferenceGroups = localPackageSourceInfo.Package.Nuspec.GetFrameworkRefGroups().ToArray(); var entry = new NugetRepositoryEntry(localPackageSourceInfo); foreach (var target in _targets) { SelectionCriteria criteria = _conventions.Criteria.ForFrameworkAndRuntime(target.Framework, target.RuntimeIdentifier); // The nunit3testadapter package publishes dll's in build/ var buildAssemblies = new PatternSet(_conventions.Properties, new[] { new PatternDefinition("build/{tfm}/{any?}"), new PatternDefinition("build/{assembly?}") }, new[] { new PatternDefinition("build/{tfm}/{assembly}"), new PatternDefinition("build/{assembly}") }); // shipped debug binaries var netcoreappdebugAssemblies = new PatternSet(_conventions.Properties, new[] { new PatternDefinition("netcoreappdebug/{tfm}/{any?}"), new PatternDefinition("netcoreappdebug/{assembly?}") }, new[] { new PatternDefinition("netcoreappdebug/{tfm}/{assembly}"), new PatternDefinition("netcoreappdebug/{assembly}") }); // The analyzer dll's are published in analyzers/ or analyzers/dotnet/cs/ var analyzerAssemblies = new PatternSet(_conventions.Properties, new [] { new PatternDefinition("analyzers/dotnet/cs/{assembly?}"), new PatternDefinition("analyzers/{assembly?}") }, new [] { new PatternDefinition("analyzers/dotnet/cs/{assembly}"), new PatternDefinition("analyzers/{assembly}") }); AddIfNotNull(entry.RefItemGroups, target.Framework, collection.FindBestItemGroup(criteria, _conventions.Patterns.CompileRefAssemblies, _conventions.Patterns.CompileLibAssemblies) ?.Items); AddIfNotNull(entry.RuntimeItemGroups, target.Framework, collection.FindBestItemGroup(criteria, _conventions.Patterns.RuntimeAssemblies, _conventions.Patterns.NativeLibraries, buildAssemblies) ?.Items.Where(IsDll)); AddIfNotNull(entry.DebugRuntimeItemGroups, target.Framework, collection.FindItemGroups(netcoreappdebugAssemblies) .SingleOrDefault() ?.Items.Where(IsDll)); AddIfNotNull(entry.ContentFileGroups, target.Framework, collection.FindBestItemGroup(criteria, _conventions.Patterns.ContentFiles) ?.Items); AddIfNotNull(entry.AnalyzerItemGroups, target.Framework, collection.FindItemGroups(analyzerAssemblies) .SingleOrDefault() ?.Items); // Merge FrameworkReferences with normal PackageReferences var dependencies = NuGetFrameworkUtility.GetNearest(allPackageDependencyGroups, target.Framework); var frameworks = NuGetFrameworkUtility.GetNearest(frameworkReferenceGroups, target.Framework); if (dependencies != null || frameworks != null) { entry.DependencyGroups.Add(new PackageDependencyGroup( dependencies?.TargetFramework ?? frameworks?.TargetFramework, new[] { frameworks?.FrameworkReferences.Select(FrameworkDependencyResolver.ConvertToDependency), dependencies?.Packages, } .SelectMany(v => v ?? Array.Empty <PackageDependency>()))); } } return(entry);
private MSBuildRestoreResult RestoreMSBuildFiles(PackageSpec project, IEnumerable <RestoreTargetGraph> targetGraphs, NuGetv3LocalRepository repository, RemoteWalkContext context) { // Get the project graph var projectFrameworks = project.TargetFrameworks.Select(f => f.FrameworkName).ToList(); // Non-Msbuild projects should skip targets and treat it as success if (!context.IsMsBuildBased) { return(new MSBuildRestoreResult(project.Name, project.BaseDirectory, success: true)); } // Invalid msbuild projects should write out an msbuild error target if (projectFrameworks.Count != 1 || !targetGraphs.Any()) { return(new MSBuildRestoreResult(project.Name, project.BaseDirectory, success: false)); } // Gather props and targets to write out var graph = targetGraphs .Single(g => g.Framework.Equals(projectFrameworks[0]) && string.IsNullOrEmpty(g.RuntimeIdentifier)); var pathResolver = new VersionFolderPathResolver(repository.RepositoryRoot); var flattenedFlags = IncludeFlagUtils.FlattenDependencyTypes(_includeFlagGraphs, _request.Project, graph); var targets = new List <string>(); var props = new List <string>(); foreach (var library in graph.Flattened .Distinct() .OrderBy(g => g.Data.Match.Library)) { var includeLibrary = true; LibraryIncludeFlags libraryFlags; if (flattenedFlags.TryGetValue(library.Key.Name, out libraryFlags)) { includeLibrary = libraryFlags.HasFlag(LibraryIncludeFlags.Build); } // Skip libraries that do not include build files such as transitive packages if (includeLibrary) { var packageIdentity = new PackageIdentity(library.Key.Name, library.Key.Version); IList <string> packageFiles; context.PackageFileCache.TryGetValue(packageIdentity, out packageFiles); if (packageFiles != null) { var contentItemCollection = new ContentItemCollection(); contentItemCollection.Load(packageFiles); // Find MSBuild thingies var groups = contentItemCollection.FindItemGroups(graph.Conventions.Patterns.MSBuildFiles); // Find the nearest msbuild group, this can include the root level Any group. var buildItems = NuGetFrameworkUtility.GetNearest( groups, graph.Framework, group => group.Properties[ManagedCodeConventions.PropertyNames.TargetFrameworkMoniker] as NuGetFramework); if (buildItems != null) { // We need to additionally filter to items that are named "{packageId}.targets" and "{packageId}.props" // Filter by file name here and we'll filter by extension when we add things to the lists. var items = buildItems.Items .Where(item => Path.GetFileNameWithoutExtension(item.Path) .Equals(library.Key.Name, StringComparison.OrdinalIgnoreCase)) .ToList(); targets.AddRange(items .Where(c => Path.GetExtension(c.Path).Equals(".targets", StringComparison.OrdinalIgnoreCase)) .Select(c => Path.Combine(pathResolver.GetPackageDirectory(library.Key.Name, library.Key.Version), c.Path.Replace('/', Path.DirectorySeparatorChar)))); props.AddRange(items .Where(c => Path.GetExtension(c.Path).Equals(".props", StringComparison.OrdinalIgnoreCase)) .Select(c => Path.Combine(pathResolver.GetPackageDirectory(library.Key.Name, library.Key.Version), c.Path.Replace('/', Path.DirectorySeparatorChar)))); } } } } return(new MSBuildRestoreResult(project.Name, project.BaseDirectory, repository.RepositoryRoot, props, targets)); }
/// <summary> /// This method combines the logic used in restore operations to make a determination about the TFM supported by the package. /// We have curated a set of compatibility requirements for our needs in NuGet.org. The client logic can be found here: /// https://github.com/NuGet/NuGet.Client/blob/63255047fe7052cc33b763356ff995d9166f719e/src/NuGet.Core/NuGet.Commands/RestoreCommand/CompatibilityChecker.cs#L252-L294 /// https://github.com/NuGet/NuGet.Client/blob/63255047fe7052cc33b763356ff995d9166f719e/src/NuGet.Core/NuGet.Commands/RestoreCommand/CompatibilityChecker.cs#L439-L442 /// ...and our combination of these elements is below. /// The logic is essentially this: /// - Determine whether we're looking at a tools package. In this case we will use tools "pattern sets" (collections of file patterns /// defined in <see cref="ManagedCodeConventions" />) to assess which frameworks are targeted by the package. /// - If this isn't a tools package, we look for build-time, runtime, content and resource file patterns /// For added details on the various cases, see unit tests targeting this method. /// </summary> public virtual IEnumerable <NuGetFramework> GetSupportedFrameworks(NuspecReader nuspecReader, IList <string> packageFiles) { var supportedTFMs = Enumerable.Empty <NuGetFramework>(); if (packageFiles != null && packageFiles.Any() && nuspecReader != null) { // Setup content items for analysis var items = new ContentItemCollection(); items.Load(packageFiles); var runtimeGraph = new RuntimeGraph(); var conventions = new ManagedCodeConventions(runtimeGraph); // Let's test for tools packages first--they're a special case var groups = Enumerable.Empty <ContentItemGroup>(); var packageTypes = nuspecReader.GetPackageTypes(); if (packageTypes.Count == 1 && (packageTypes[0] == PackageType.DotnetTool || packageTypes[0] == PackageType.DotnetCliTool)) { // Only a package that is a tool package (and nothing else) will be matched against tools pattern set groups = items.FindItemGroups(conventions.Patterns.ToolsAssemblies); } else { // Gather together a list of pattern sets indicating the kinds of packages we wish to evaluate var patterns = new[] { conventions.Patterns.CompileRefAssemblies, conventions.Patterns.CompileLibAssemblies, conventions.Patterns.RuntimeAssemblies, conventions.Patterns.ContentFiles, conventions.Patterns.ResourceAssemblies, }; // Add MSBuild to this list, but we need to ensure we have package assets before they make the cut. // A series of files in the right places won't matter if there's no {id}.props|targets. var msbuildPatterns = new[] { conventions.Patterns.MSBuildFiles, conventions.Patterns.MSBuildMultiTargetingFiles, }; // We'll create a set of "groups" --these are content items which satisfy file pattern sets var standardGroups = patterns .SelectMany(p => items.FindItemGroups(p)); // Filter out MSBuild assets that don't match the package ID and append to groups we already have var packageId = nuspecReader.GetId(); var msbuildGroups = msbuildPatterns .SelectMany(p => items.FindItemGroups(p)) .Where(g => HasBuildItemsForPackageId(g.Items, packageId)); groups = standardGroups.Concat(msbuildGroups); } // Now that we have a collection of groups which have made it through the pattern set filter, let's transform them into TFMs supportedTFMs = groups .SelectMany(p => p.Properties) .Where(pair => pair.Key == ManagedCodeConventions.PropertyNames.TargetFrameworkMoniker) .Select(pair => pair.Value) .Cast <NuGetFramework>() .Distinct(); } return(supportedTFMs); }