diff --git a/TestAssets/TestProjects/PortableTests/PortableAppCompilationContext/project.json b/TestAssets/TestProjects/PortableTests/PortableAppCompilationContext/project.json index a016cf549..16acba048 100644 --- a/TestAssets/TestProjects/PortableTests/PortableAppCompilationContext/project.json +++ b/TestAssets/TestProjects/PortableTests/PortableAppCompilationContext/project.json @@ -3,7 +3,9 @@ "emitEntryPoint": true, "preserveCompilationContext": true }, - "dependencies": {}, + "dependencies": { + "Microsoft.CodeAnalysis.CSharp": "1.3.0-beta1-20160425-01" + }, "frameworks": { "netcoreapp1.0": { "dependencies": { diff --git a/scripts/dotnet-cli-build/CompileTargets.cs b/scripts/dotnet-cli-build/CompileTargets.cs index b2ab372d8..f9ff6ee49 100644 --- a/scripts/dotnet-cli-build/CompileTargets.cs +++ b/scripts/dotnet-cli-build/CompileTargets.cs @@ -694,30 +694,40 @@ namespace Microsoft.DotNet.Cli.Build deps = JObject.ReadFrom(reader); } - var target = deps["targets"][deps["runtimeTarget"]["name"].Value()]; - var library = target.Children().First(); - var version = library.Name.Substring(library.Name.IndexOf('/') + 1); - if (newName == null) + string version = null; + foreach (JProperty target in deps["targets"]) { - library.Remove(); + var targetLibrary = target.Value.Children().FirstOrDefault(); + if (targetLibrary == null) + { + continue; + } + version = targetLibrary.Name.Substring(targetLibrary.Name.IndexOf('/') + 1); + if (newName == null) + { + targetLibrary.Remove(); + } + else + { + targetLibrary.Replace(new JProperty(newName + '/' + version, targetLibrary.Value)); + } } - else + if (version != null) { - library.Replace(new JProperty(newName + '/' + version, library.Value)); - } - library = deps["libraries"].Children().First(); - if (newName == null) - { - library.Remove(); - } - else - { - library.Replace(new JProperty(newName + '/' + version, library.Value)); - } - using (var file = File.CreateText(depsFile)) - using (var writer = new JsonTextWriter(file) { Formatting = Formatting.Indented }) - { - deps.WriteTo(writer); + var library = deps["libraries"].Children().First(); + if (newName == null) + { + library.Remove(); + } + else + { + library.Replace(new JProperty(newName + '/' + version, library.Value)); + } + using (var file = File.CreateText(depsFile)) + using (var writer = new JsonTextWriter(file) { Formatting = Formatting.Indented }) + { + deps.WriteTo(writer); + } } } diff --git a/src/Microsoft.DotNet.ProjectModel/ProjectModelPlatformExtensions.cs b/src/Microsoft.DotNet.ProjectModel/ProjectModelPlatformExtensions.cs new file mode 100644 index 000000000..4c50c1102 --- /dev/null +++ b/src/Microsoft.DotNet.ProjectModel/ProjectModelPlatformExtensions.cs @@ -0,0 +1,50 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Microsoft.DotNet.ProjectModel.Compilation; +using Microsoft.DotNet.ProjectModel.Graph; + +namespace Microsoft.DotNet.ProjectModel +{ + public static class ProjectModelPlatformExtensions + { + public static IEnumerable ExcludePlatformExports(this ProjectContext context, IEnumerable allExports) + { + var exclusionList = context.GetPlatformExclusionList(allExports); + return allExports.Where(e => !exclusionList.Contains(e.Library.Identity.Name)); + } + + public static HashSet GetPlatformExclusionList(this ProjectContext context, IEnumerable allExports) + { + var exclusionList = new HashSet(); + var redistPackage = context.PlatformLibrary; + if (redistPackage == null) + { + return exclusionList; + } + var exports = allExports + .Where(e => e.Library.Identity.Type.Equals(LibraryType.Package)) + .ToDictionary(e => e.Library.Identity.Name); + + var redistExport = exports[redistPackage.Identity.Name]; + + exclusionList.Add(redistExport.Library.Identity.Name); + CollectDependencies(exports, redistExport.Library.Dependencies, exclusionList); + return exclusionList; + } + + private static void CollectDependencies(Dictionary exports, IEnumerable dependencies, HashSet exclusionList) + { + foreach (var dependency in dependencies) + { + var export = exports[dependency.Name]; + if (export.Library.Identity.Version.Equals(dependency.VersionRange.MinVersion)) + { + exclusionList.Add(export.Library.Identity.Name); + CollectDependencies(exports, export.Library.Dependencies, exclusionList); + } + } + } + } +} diff --git a/src/Microsoft.Extensions.DependencyModel/DependencyContext.cs b/src/Microsoft.Extensions.DependencyModel/DependencyContext.cs index 353f59332..4999ba9c3 100644 --- a/src/Microsoft.Extensions.DependencyModel/DependencyContext.cs +++ b/src/Microsoft.Extensions.DependencyModel/DependencyContext.cs @@ -8,34 +8,6 @@ using System.Reflection; namespace Microsoft.Extensions.DependencyModel { - public class TargetInfo - { - public TargetInfo(string framework, - string runtime, - string runtimeSignature, - bool isPortable) - { - if (string.IsNullOrEmpty(framework)) - { - throw new ArgumentException(nameof(framework)); - } - - Framework = framework; - Runtime = runtime; - RuntimeSignature = runtimeSignature; - IsPortable = isPortable; - } - - public string Framework { get; } - - public string Runtime { get; } - - public string RuntimeSignature { get; } - - public bool IsPortable { get; } - - } - public class DependencyContext { private static readonly Lazy _defaultContext = new Lazy(LoadDefault); diff --git a/src/Microsoft.Extensions.DependencyModel/DependencyContextLoader.cs b/src/Microsoft.Extensions.DependencyModel/DependencyContextLoader.cs index 7f42f4f10..a1deb0fff 100644 --- a/src/Microsoft.Extensions.DependencyModel/DependencyContextLoader.cs +++ b/src/Microsoft.Extensions.DependencyModel/DependencyContextLoader.cs @@ -11,8 +11,6 @@ namespace Microsoft.Extensions.DependencyModel { public class DependencyContextLoader { - private static Lazy _depsFiles = new Lazy(GetHostDepsList); - private const string DepsJsonExtension = ".deps.json"; private readonly string _entryPointDepsLocation; @@ -21,8 +19,8 @@ namespace Microsoft.Extensions.DependencyModel private readonly IDependencyContextReader _jsonReader; public DependencyContextLoader() : this( - GetDefaultEntrypointDepsLocation(), - GetDefaultRuntimeDepsLocation(), + DependencyContextPaths.Current.Application, + DependencyContextPaths.Current.SharedRuntime, FileSystemWrapper.Default, new DependencyContextJsonReader()) { @@ -129,36 +127,5 @@ namespace Microsoft.Extensions.DependencyModel return null; } - - private static string GetDefaultRuntimeDepsLocation() - { - var deps = _depsFiles.Value; - if (deps != null && deps.Length > 1) - { - return deps[1]; - } - return null; - } - - private static string GetDefaultEntrypointDepsLocation() - { - var deps = _depsFiles.Value; - if (deps != null && deps.Length > 0) - { - return deps[0]; - } - return null; - } - - private static string[] GetHostDepsList() - { - // TODO: We're going to replace this with AppContext.GetData - var appDomainType = typeof(object).GetTypeInfo().Assembly?.GetType("System.AppDomain"); - var currentDomain = appDomainType?.GetProperty("CurrentDomain")?.GetValue(null); - var deps = appDomainType?.GetMethod("GetData")?.Invoke(currentDomain, new[] { "APP_CONTEXT_DEPS_FILES" }); - - return (deps as string)?.Split(new [] { ';' }, StringSplitOptions.RemoveEmptyEntries); - } - } } diff --git a/src/Microsoft.Extensions.DependencyModel/DependencyContextPaths.cs b/src/Microsoft.Extensions.DependencyModel/DependencyContextPaths.cs new file mode 100644 index 000000000..1374d3a1f --- /dev/null +++ b/src/Microsoft.Extensions.DependencyModel/DependencyContextPaths.cs @@ -0,0 +1,37 @@ +using System; + +namespace Microsoft.Extensions.DependencyModel +{ + internal class DependencyContextPaths + { + private static readonly string DepsFilesProperty = "APP_CONTEXT_DEPS_FILES"; + + public static DependencyContextPaths Current { get; } = GetCurrent(); + + public string Application { get; } + + public string SharedRuntime { get; } + + public DependencyContextPaths(string application, string sharedRuntime) + { + Application = application; + SharedRuntime = sharedRuntime; + } + + private static DependencyContextPaths GetCurrent() + { +#if NETSTANDARD1_5 + var deps = AppContext.GetData(DepsFilesProperty); +#else + var deps = AppDomain.CurrentDomain.GetData(DepsFilesProperty); +#endif + var files = (deps as string)?.Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries); + + return new DependencyContextPaths( + files != null && files.Length > 0 ? files[0] : null, + files != null && files.Length > 1 ? files[1] : null + ); + + } + } +} \ No newline at end of file diff --git a/src/Microsoft.Extensions.DependencyModel/Resolution/AppBaseCompilationAssemblyResolver.cs b/src/Microsoft.Extensions.DependencyModel/Resolution/AppBaseCompilationAssemblyResolver.cs index 2f956f666..8ff49175a 100644 --- a/src/Microsoft.Extensions.DependencyModel/Resolution/AppBaseCompilationAssemblyResolver.cs +++ b/src/Microsoft.Extensions.DependencyModel/Resolution/AppBaseCompilationAssemblyResolver.cs @@ -11,45 +11,49 @@ namespace Microsoft.Extensions.DependencyModel.Resolution { public class AppBaseCompilationAssemblyResolver : ICompilationAssemblyResolver { + private static string RefsDirectoryName = "refs"; private readonly IFileSystem _fileSystem; private readonly string _basePath; + private readonly DependencyContextPaths _dependencyContextPaths; public AppBaseCompilationAssemblyResolver() : this(FileSystemWrapper.Default) { } - public AppBaseCompilationAssemblyResolver(string basePath) : this(FileSystemWrapper.Default, basePath) + public AppBaseCompilationAssemblyResolver(string basePath) + : this(FileSystemWrapper.Default, basePath, DependencyContextPaths.Current) { } internal AppBaseCompilationAssemblyResolver(IFileSystem fileSystem) - : this(fileSystem, ApplicationEnvironment.ApplicationBasePath) + : this(fileSystem, ApplicationEnvironment.ApplicationBasePath, DependencyContextPaths.Current) { } - internal AppBaseCompilationAssemblyResolver(IFileSystem fileSystem, string basePath) + internal AppBaseCompilationAssemblyResolver(IFileSystem fileSystem, string basePath, DependencyContextPaths dependencyContextPaths) { _fileSystem = fileSystem; _basePath = basePath; + _dependencyContextPaths = dependencyContextPaths; } public bool TryResolveAssemblyPaths(CompilationLibrary library, List assemblies) { var isProject = string.Equals(library.Type, "project", StringComparison.OrdinalIgnoreCase); - + var isPackage = string.Equals(library.Type, "package", StringComparison.OrdinalIgnoreCase); if (!isProject && - !string.Equals(library.Type, "package", StringComparison.OrdinalIgnoreCase) && + !isPackage && !string.Equals(library.Type, "referenceassembly", StringComparison.OrdinalIgnoreCase)) { return false; } - var refsPath = Path.Combine(_basePath, "refs"); - var hasRefs = _fileSystem.Directory.Exists(refsPath); + var refsPath = Path.Combine(_basePath, RefsDirectoryName); + var isPublished = _fileSystem.Directory.Exists(refsPath); - // Resolving packages and reference assebmlies requires refs folder to exist - if (!isProject && !hasRefs) + // Resolving reference assebmlies requires refs folder to exist + if (!isProject && !isPackage && !isPublished) { return false; } @@ -59,11 +63,24 @@ namespace Microsoft.Extensions.DependencyModel.Resolution _basePath }; - if (hasRefs) + if (isPublished) { directories.Insert(0, refsPath); } + // Only packages can come from shared runtime + var sharedPath = _dependencyContextPaths.SharedRuntime; + if (isPublished && isPackage && !string.IsNullOrEmpty(sharedPath)) + { + var sharedDirectory = Path.GetDirectoryName(sharedPath); + var sharedRefs = Path.Combine(sharedDirectory, RefsDirectoryName); + if (_fileSystem.Directory.Exists(sharedRefs)) + { + directories.Add(sharedRefs); + } + directories.Add(sharedDirectory); + } + foreach (var assembly in library.Assemblies) { bool resolved = false; @@ -81,9 +98,15 @@ namespace Microsoft.Extensions.DependencyModel.Resolution if (!resolved) { + // throw in case when we are published app and nothing found + // because we cannot rely on nuget package cache in this case + if (isPublished) + { throw new InvalidOperationException( $"Can not find assembly file {assemblyFile} at '{string.Join(",", directories)}'"); } + return false; + } } return true; diff --git a/src/Microsoft.Extensions.DependencyModel/TargetInfo.cs b/src/Microsoft.Extensions.DependencyModel/TargetInfo.cs new file mode 100644 index 000000000..56bab154c --- /dev/null +++ b/src/Microsoft.Extensions.DependencyModel/TargetInfo.cs @@ -0,0 +1,34 @@ +// Copyright (c) .NET Foundation and contributors. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +using System; + +namespace Microsoft.Extensions.DependencyModel +{ + public class TargetInfo + { + public TargetInfo(string framework, + string runtime, + string runtimeSignature, + bool isPortable) + { + if (string.IsNullOrEmpty(framework)) + { + throw new ArgumentException(nameof(framework)); + } + + Framework = framework; + Runtime = runtime; + RuntimeSignature = runtimeSignature; + IsPortable = isPortable; + } + + public string Framework { get; } + + public string Runtime { get; } + + public string RuntimeSignature { get; } + + public bool IsPortable { get; } + + } +} \ No newline at end of file diff --git a/src/dotnet/commands/dotnet-publish/PublishCommand.cs b/src/dotnet/commands/dotnet-publish/PublishCommand.cs index 5b0fe4711..cccfee24e 100644 --- a/src/dotnet/commands/dotnet-publish/PublishCommand.cs +++ b/src/dotnet/commands/dotnet-publish/PublishCommand.cs @@ -129,18 +129,12 @@ namespace Microsoft.DotNet.Tools.Publish // Use a library exporter to collect publish assets var exporter = context.CreateExporter(configuration, buildBasePath); - // Collect all exports and organize them - var packageExports = exporter.GetAllExports() - .Where(e => e.Library.Identity.Type.Equals(LibraryType.Package)) - .ToDictionary(e => e.Library.Identity.Name); - var collectExclusionList = context.IsPortable ? GetExclusionList(context, packageExports) : new HashSet(); - // Get the output paths used by the call to `dotnet build` above (since we didn't pass `--output`, they will be different from // our current output paths) var buildOutputPaths = context.GetOutputPaths(configuration, buildBasePath); var exports = exporter.GetAllExports(); - foreach (var export in exports.Where(e => !collectExclusionList.Contains(e.Library.Identity.Name))) + foreach (var export in context.ExcludePlatformExports(exports)) { Reporter.Verbose.WriteLine($"publish: Publishing {export.Library.Identity.ToString().Green().Bold()} ..."); @@ -160,6 +154,13 @@ namespace Microsoft.DotNet.Tools.Publish File.Copy(resourceAsset.Asset.ResolvedPath, Path.Combine(dir, resourceAsset.Asset.FileName), overwrite: true); } } + foreach (var export in exports) + { + if (options.PreserveCompilationContext.GetValueOrDefault()) + { + PublishRefs(export, outputPath); + } + } if (context.ProjectFile.HasRuntimeOutput(configuration) && !context.TargetFramework.IsDesktop()) { @@ -171,14 +172,6 @@ namespace Microsoft.DotNet.Tools.Publish outputPath); } - if (options.PreserveCompilationContext.GetValueOrDefault()) - { - foreach (var export in exports) - { - PublishRefs(export, outputPath, !collectExclusionList.Contains(export.Library.Identity.Name)); - } - } - var contentFiles = new ContentFiles(context); if (context.ProjectFile.PublishOptions != null) @@ -265,41 +258,7 @@ namespace Microsoft.DotNet.Tools.Publish return result == 0; } - private HashSet GetExclusionList(ProjectContext context, Dictionary exports) - { - var exclusionList = new HashSet(); - var redistPackages = context.RootProject.Dependencies - .Where(r => r.Type.Equals(LibraryDependencyType.Platform)) - .ToList(); - if (redistPackages.Count == 0) - { - return exclusionList; - } - else if (redistPackages.Count > 1) - { - throw new InvalidOperationException("Multiple packages with type: \"platform\" were specified!"); - } - var redistExport = exports[redistPackages[0].Name]; - - exclusionList.Add(redistExport.Library.Identity.Name); - CollectDependencies(exports, redistExport.Library.Dependencies, exclusionList); - return exclusionList; - } - - private void CollectDependencies(Dictionary exports, IEnumerable dependencies, HashSet exclusionList) - { - foreach (var dependency in dependencies) - { - var export = exports[dependency.Name]; - if (export.Library.Identity.Version.Equals(dependency.VersionRange.MinVersion)) - { - exclusionList.Add(export.Library.Identity.Name); - CollectDependencies(exports, export.Library.Dependencies, exclusionList); - } - } - } - - private static void PublishRefs(LibraryExport export, string outputPath, bool deduplicate) + private static void PublishRefs(LibraryExport export, string outputPath) { var refsPath = Path.Combine(outputPath, "refs"); if (!Directory.Exists(refsPath)) @@ -311,11 +270,12 @@ namespace Microsoft.DotNet.Tools.Publish var runtimeAssemblies = new HashSet(export.RuntimeAssemblyGroups.GetDefaultAssets()); foreach (var compilationAssembly in export.CompilationAssemblies) { - if (!deduplicate || !runtimeAssemblies.Contains(compilationAssembly)) + if (runtimeAssemblies.Contains(compilationAssembly)) { - var destFileName = Path.Combine(refsPath, Path.GetFileName(compilationAssembly.ResolvedPath)); - File.Copy(compilationAssembly.ResolvedPath, destFileName, overwrite: true); + continue; } + var destFileName = Path.Combine(refsPath, Path.GetFileName(compilationAssembly.ResolvedPath)); + File.Copy(compilationAssembly.ResolvedPath, destFileName, overwrite: true); } } diff --git a/test/Microsoft.Extensions.DependencyModel.Tests/AppBaseResolverTests.cs b/test/Microsoft.Extensions.DependencyModel.Tests/AppBaseResolverTests.cs index eb1ce55ca..382b7f329 100644 --- a/test/Microsoft.Extensions.DependencyModel.Tests/AppBaseResolverTests.cs +++ b/test/Microsoft.Extensions.DependencyModel.Tests/AppBaseResolverTests.cs @@ -4,13 +4,12 @@ using System; using System.Collections.Generic; using System.IO; -using System.Linq; -using System.Threading.Tasks; -using Microsoft.Extensions.DependencyModel; +using Microsoft.Extensions.EnvironmentAbstractions; using Microsoft.Extensions.DependencyModel.Resolution; using Xunit; using FluentAssertions; + namespace Microsoft.Extensions.DependencyModel.Tests { public class AppBaseResolverTests @@ -18,6 +17,11 @@ namespace Microsoft.Extensions.DependencyModel.Tests private static string BasePath = Path.Combine("Base","Path"); private static string BasePathRefs = Path.Combine(BasePath, "refs"); + private static string SharedFxPath = Path.Combine("shared", "fx"); + private static string SharedFxPathRefs = Path.Combine(SharedFxPath, "refs"); + + private static DependencyContextPaths DependencyContextPaths = new DependencyContextPaths(null, Path.Combine(SharedFxPath, "deps.json")); + [Fact] public void ResolvesProjectType() { @@ -25,7 +29,7 @@ namespace Microsoft.Extensions.DependencyModel.Tests .Create() .AddFiles(BasePathRefs, TestLibraryFactory.DefaultAssembly) .Build(); - var resolver = new AppBaseCompilationAssemblyResolver(fileSystem, BasePath); + var resolver = CreateResolver(fileSystem); var library = TestLibraryFactory.Create( TestLibraryFactory.ProjectType, assemblies: TestLibraryFactory.EmptyAssemblies); @@ -42,7 +46,7 @@ namespace Microsoft.Extensions.DependencyModel.Tests .Create() .AddFiles(BasePathRefs, TestLibraryFactory.DefaultAssembly) .Build(); - var resolver = new AppBaseCompilationAssemblyResolver(fileSystem, BasePath); + var resolver = CreateResolver(fileSystem); var library = TestLibraryFactory.Create( TestLibraryFactory.PackageType, assemblies: TestLibraryFactory.EmptyAssemblies); @@ -59,7 +63,7 @@ namespace Microsoft.Extensions.DependencyModel.Tests .Create() .AddFiles(BasePathRefs, TestLibraryFactory.DefaultAssembly) .Build(); - var resolver = new AppBaseCompilationAssemblyResolver(fileSystem, BasePath); + var resolver = CreateResolver(fileSystem); var library = TestLibraryFactory.Create( TestLibraryFactory.ReferenceAssemblyType, assemblies: TestLibraryFactory.EmptyAssemblies); @@ -79,7 +83,7 @@ namespace Microsoft.Extensions.DependencyModel.Tests var library = TestLibraryFactory.Create( TestLibraryFactory.ReferenceAssemblyType, assemblies: TestLibraryFactory.TwoAssemblies); - var resolver = new AppBaseCompilationAssemblyResolver(fileSystem, BasePath); + var resolver = CreateResolver(fileSystem); var assemblies = new List(); var result = resolver.TryResolveAssemblyPaths(library, assemblies); @@ -98,7 +102,7 @@ namespace Microsoft.Extensions.DependencyModel.Tests var library = TestLibraryFactory.Create( TestLibraryFactory.ProjectType, assemblies: TestLibraryFactory.TwoAssemblies); - var resolver = new AppBaseCompilationAssemblyResolver(fileSystem, BasePath); + var resolver = CreateResolver(fileSystem); var assemblies = new List(); var result = resolver.TryResolveAssemblyPaths(library, assemblies); @@ -120,7 +124,7 @@ namespace Microsoft.Extensions.DependencyModel.Tests var library = TestLibraryFactory.Create( TestLibraryFactory.ReferenceAssemblyType, assemblies: TestLibraryFactory.TwoAssemblies); - var resolver = new AppBaseCompilationAssemblyResolver(fileSystem, BasePath); + var resolver = CreateResolver(fileSystem); var assemblies = new List(); var exception = Assert.Throws(() => resolver.TryResolveAssemblyPaths(library, assemblies)); @@ -141,7 +145,7 @@ namespace Microsoft.Extensions.DependencyModel.Tests var library = TestLibraryFactory.Create( TestLibraryFactory.ReferenceAssemblyType, assemblies: TestLibraryFactory.TwoAssemblies); - var resolver = new AppBaseCompilationAssemblyResolver(fileSystem, BasePath); + var resolver = CreateResolver(fileSystem); var assemblies = new List(); var result = resolver.TryResolveAssemblyPaths(library, assemblies); @@ -164,7 +168,7 @@ namespace Microsoft.Extensions.DependencyModel.Tests TestLibraryFactory.ReferenceAssemblyType, assemblies: TestLibraryFactory.TwoAssemblies); - var resolver = new AppBaseCompilationAssemblyResolver(fileSystem, BasePath); + var resolver = CreateResolver(fileSystem); var assemblies = new List(); var result = resolver.TryResolveAssemblyPaths(library, assemblies); @@ -187,7 +191,7 @@ namespace Microsoft.Extensions.DependencyModel.Tests TestLibraryFactory.ReferenceAssemblyType, assemblies: TestLibraryFactory.TwoAssemblies); - var resolver = new AppBaseCompilationAssemblyResolver(fileSystem, BasePath); + var resolver = CreateResolver(fileSystem); var assemblies = new List(); var result = resolver.TryResolveAssemblyPaths(library, assemblies); @@ -205,12 +209,14 @@ namespace Microsoft.Extensions.DependencyModel.Tests .Create() .AddFiles(BasePath, TestLibraryFactory.DefaultAssembly) .AddFiles(BasePathRefs, TestLibraryFactory.DefaultAssembly) + .AddFile(SharedFxPath, TestLibraryFactory.DefaultAssembly) + .AddFile(SharedFxPathRefs, TestLibraryFactory.DefaultAssembly) .Build(); var library = TestLibraryFactory.Create( - TestLibraryFactory.ReferenceAssemblyType + TestLibraryFactory.PackageType ); - var resolver = new AppBaseCompilationAssemblyResolver(fileSystem, BasePath); + var resolver = CreateResolver(fileSystem); var assemblies = new List(); var result = resolver.TryResolveAssemblyPaths(library, assemblies); @@ -220,6 +226,128 @@ namespace Microsoft.Extensions.DependencyModel.Tests assemblies.Should().Contain(Path.Combine(BasePathRefs, TestLibraryFactory.DefaultAssembly)); } + [Fact] + public void SearchesInSharedFxRefsPathForPublishedPortable() + { + var fileSystem = FileSystemMockBuilder + .Create() + .AddFiles(BasePathRefs, TestLibraryFactory.SecondAssembly) + .AddFiles(SharedFxPathRefs, TestLibraryFactory.DefaultAssembly) + .Build(); + var library = TestLibraryFactory.Create( + TestLibraryFactory.PackageType + ); + var resolver = CreateResolver(fileSystem); + var assemblies = new List(); + var result = resolver.TryResolveAssemblyPaths(library, assemblies); + + Assert.True(result); + assemblies.Should().HaveCount(1); + assemblies.Should().Contain(Path.Combine(SharedFxPathRefs, TestLibraryFactory.DefaultAssembly)); + } + + [Fact] + public void SearchesInSharedFxPathForPublishedPortable() + { + var fileSystem = FileSystemMockBuilder + .Create() + .AddFiles(BasePathRefs, TestLibraryFactory.SecondAssembly) + .AddFiles(SharedFxPath, TestLibraryFactory.DefaultAssembly) + .Build(); + var library = TestLibraryFactory.Create( + TestLibraryFactory.PackageType + ); + + var resolver = CreateResolver(fileSystem); + var assemblies = new List(); + + var result = resolver.TryResolveAssemblyPaths(library, assemblies); + + Assert.True(result); + assemblies.Should().HaveCount(1); + assemblies.Should().Contain(Path.Combine(SharedFxPath, TestLibraryFactory.DefaultAssembly)); + } + + [Fact] + public void PrefersSharedFxPathRefsPathPublishedPortable() + { + var fileSystem = FileSystemMockBuilder + .Create() + .AddFiles(BasePathRefs, TestLibraryFactory.SecondAssembly) + .AddFiles(SharedFxPath, TestLibraryFactory.DefaultAssembly) + .AddFiles(SharedFxPathRefs, TestLibraryFactory.DefaultAssembly) + .Build(); + var library = TestLibraryFactory.Create( + TestLibraryFactory.PackageType + ); + + var resolver = CreateResolver(fileSystem); + var assemblies = new List(); + + var result = resolver.TryResolveAssemblyPaths(library, assemblies); + + Assert.True(result); + assemblies.Should().HaveCount(1); + assemblies.Should().Contain(Path.Combine(SharedFxPathRefs, TestLibraryFactory.DefaultAssembly)); + } + + [Fact] + public void SkipsSharedFxPathForNonPublishedPortable() + { + var fileSystem = FileSystemMockBuilder + .Create() + .AddFiles(SharedFxPath, TestLibraryFactory.DefaultAssembly) + .AddFiles(SharedFxPathRefs, TestLibraryFactory.DefaultAssembly) + .Build(); + var library = TestLibraryFactory.Create( + TestLibraryFactory.PackageType + ); + + var resolver = CreateResolver(fileSystem); + var assemblies = new List(); + + var result = resolver.TryResolveAssemblyPaths(library, assemblies); + Assert.False(result); + } + + [Fact] + public void ShouldThrowForNonResolvedInPublishedApps() + { + var fileSystem = FileSystemMockBuilder + .Create() + .AddFiles(BasePathRefs, TestLibraryFactory.SecondAssembly) + .Build(); + var library = TestLibraryFactory.Create( + TestLibraryFactory.PackageType + ); + + var resolver = CreateResolver(fileSystem); + var assemblies = new List(); + + Assert.Throws(() => resolver.TryResolveAssemblyPaths(library, assemblies)); + } + + [Fact] + public void ShouldSkipForNonResolvedInNonPublishedApps() + { + var fileSystem = FileSystemMockBuilder + .Create() + .Build(); + var library = TestLibraryFactory.Create( + TestLibraryFactory.PackageType + ); + + var resolver = CreateResolver(fileSystem); + var assemblies = new List(); + + var result = resolver.TryResolveAssemblyPaths(library, assemblies); + Assert.False(result); + } + + private static AppBaseCompilationAssemblyResolver CreateResolver(IFileSystem fileSystem) + { + return new AppBaseCompilationAssemblyResolver(fileSystem, BasePath, DependencyContextPaths); + } } } diff --git a/test/dotnet-publish.Tests/PublishPortableTests.cs b/test/dotnet-publish.Tests/PublishPortableTests.cs index 9283b85dd..a7f774b22 100644 --- a/test/dotnet-publish.Tests/PublishPortableTests.cs +++ b/test/dotnet-publish.Tests/PublishPortableTests.cs @@ -1,8 +1,9 @@ -using Microsoft.DotNet.TestFramework; -using Microsoft.DotNet.Tools.Test.Utilities; -using System; +using System; using System.Collections.Generic; using System.IO; +using Microsoft.DotNet.TestFramework; +using Microsoft.DotNet.Tools.Test.Utilities; +using FluentAssertions; using Xunit; namespace Microsoft.DotNet.Tools.Publish.Tests @@ -93,7 +94,9 @@ namespace Microsoft.DotNet.Tools.Publish.Tests publishCommand.GetOutputDirectory(true).Should().HaveFile("PortableAppCompilationContext.dll"); var refsDirectory = new DirectoryInfo(Path.Combine(publishCommand.GetOutputDirectory(true).FullName, "refs")); - // Should have compilation time assemblies + // Microsoft.CodeAnalysis.CSharp is IL only + refsDirectory.Should().NotHaveFile("Microsoft.CodeAnalysis.CSharp.dll"); + // System.IO has facede refsDirectory.Should().HaveFile("System.IO.dll"); // Libraries in which lib==ref should be deduped refsDirectory.Should().NotHaveFile("PortableAppCompilationContext.dll");