Merge pull request #960 from dotnet/pakrym/publishrefs

Copy refs only on publish
This commit is contained in:
Pavel Krymets 2016-01-29 11:41:06 -08:00
commit 07fbb3d967
9 changed files with 257 additions and 27 deletions

View file

@ -4,6 +4,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Extensions.Internal;
namespace Microsoft.DotNet.ProjectModel.Compilation
{
@ -19,5 +20,27 @@ namespace Microsoft.DotNet.ProjectModel.Compilation
RelativePath = relativePath;
ResolvedPath = resolvedPath;
}
public bool Equals(LibraryAsset other)
{
return string.Equals(Name, other.Name)
&& string.Equals(RelativePath, other.RelativePath)
&& string.Equals(ResolvedPath, other.ResolvedPath);
}
public override bool Equals(object obj)
{
if (ReferenceEquals(null, obj)) return false;
return obj is LibraryAsset && Equals((LibraryAsset) obj);
}
public override int GetHashCode()
{
var combiner = HashCodeCombiner.Start();
combiner.Add(Name);
combiner.Add(RelativePath);
combiner.Add(ResolvedPath);
return combiner.CombinedHash;
}
}
}

View file

@ -5,6 +5,7 @@ using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using Microsoft.Extensions.PlatformAbstractions;
namespace Microsoft.Extensions.DependencyModel
{
@ -12,6 +13,10 @@ namespace Microsoft.Extensions.DependencyModel
{
private static Lazy<Assembly> _entryAssembly = new Lazy<Assembly>(GetEntryAssembly);
private static string _nugetPackages = Environment.GetEnvironmentVariable("NUGET_PACKAGES") ?? GetDefaultPackageDirectory();
private static string _packageCache = Environment.GetEnvironmentVariable("DOTNET_PACKAGES_CACHE");
public CompilationLibrary(string libraryType, string packageName, string version, string hash, string[] assemblies, Dependency[] dependencies, bool serviceable)
: base(libraryType, packageName, version, hash, dependencies, serviceable)
{
@ -24,24 +29,126 @@ namespace Microsoft.Extensions.DependencyModel
{
var entryAssembly = _entryAssembly.Value;
var entryAssemblyName = entryAssembly.GetName().Name;
var basePath = GetRefsLocation();
foreach (var assembly in Assemblies)
string basePath;
string fullName;
var appBase = Path.GetDirectoryName(entryAssembly.Location);
var refsDir = Path.Combine(appBase, "refs");
var hasRefs = Directory.Exists(refsDir);
var isProject = string.Equals(LibraryType, "project", StringComparison.OrdinalIgnoreCase);
if (hasRefs || isProject)
{
if (Path.GetFileNameWithoutExtension(assembly) == entryAssemblyName)
foreach (var assembly in Assemblies)
{
yield return entryAssembly.Location;
continue;
var assemblyFile = Path.GetFileName(assembly);
if (hasRefs && TryResolveAssemblyFile(refsDir, assemblyFile, out fullName))
{
yield return fullName;
}
else if (TryResolveAssemblyFile(appBase, assemblyFile, out fullName))
{
yield return fullName;
}
else
{
var errorMessage = $"Can not find assembly file {assemblyFile} at '{appBase}'";
if (hasRefs)
{
errorMessage += $", '{refsDir}'";
}
throw new InvalidOperationException(errorMessage);
}
}
yield break;
}
else if (TryResolvePackagePath(out basePath))
{
foreach (var assembly in Assemblies)
{
if (!TryResolveAssemblyFile(basePath, assembly, out fullName))
{
throw new InvalidOperationException($"Can not find assembly file at '{fullName}'");
}
yield return fullName;
}
yield break;
}
throw new InvalidOperationException($"Can not find compilation library location for package '{PackageName}'");
}
private bool TryResolveAssemblyFile(string basePath, string assemblyPath, out string fullName)
{
fullName = Path.Combine(basePath, assemblyPath);
if (File.Exists(fullName))
{
return true;
}
return false;
}
private bool TryResolvePackagePath(out string packagePath)
{
packagePath = null;
if (!string.IsNullOrEmpty(_packageCache))
{
var hashSplitterPos = Hash.IndexOf('-');
if (hashSplitterPos <= 0 || hashSplitterPos == Hash.Length - 1)
{
throw new InvalidOperationException($"Invalid hash entry '{Hash}' for package '{PackageName}'");
}
var fullName = Path.Combine(basePath, Path.GetFileName(assembly));
if (!File.Exists(fullName))
var hashAlgorithm = Hash.Substring(0, hashSplitterPos);
var cacheHashPath = Path.Combine(_packageCache, $"{PackageName}.{Version}.nupkg.{hashAlgorithm}");
if (File.Exists(cacheHashPath) &&
File.ReadAllText(cacheHashPath) == Hash.Substring(hashSplitterPos + 1))
{
throw new InvalidOperationException($"Can not resolve assembly {assembly} location");
if (TryResolvePackagePath(_nugetPackages, out packagePath))
{
return true;
}
}
yield return fullName;
}
if (!string.IsNullOrEmpty(_nugetPackages) &&
TryResolvePackagePath(_nugetPackages, out packagePath))
{
return true;
}
return false;
}
private bool TryResolvePackagePath(string basePath, out string packagePath)
{
packagePath = Path.Combine(basePath, PackageName, Version);
if (Directory.Exists(packagePath))
{
return true;
}
return false;
}
private static string GetDefaultPackageDirectory()
{
string basePath;
if (PlatformServices.Default.Runtime.OperatingSystemPlatform == Platform.Windows)
{
basePath = Environment.GetEnvironmentVariable("USERPROFILE");
}
else
{
basePath = Environment.GetEnvironmentVariable("HOME");
}
if (string.IsNullOrEmpty(basePath))
{
return null;
}
return Path.Combine(basePath, ".nuget", "packages");
}
private static Assembly GetEntryAssembly()
{
var entryAssembly = (Assembly)typeof(Assembly).GetTypeInfo().GetDeclaredMethod("GetEntryAssembly").Invoke(null, null);
@ -51,10 +158,5 @@ namespace Microsoft.Extensions.DependencyModel
}
return entryAssembly;
}
private static string GetRefsLocation()
{
return Path.Combine(Path.GetDirectoryName(_entryAssembly.Value.Location), "refs");
}
}
}

View file

@ -10,7 +10,8 @@
"keyFile": "../../tools/Key.snk"
},
"dependencies": {
"Newtonsoft.Json": "7.0.1"
"Newtonsoft.Json": "7.0.1",
"Microsoft.Extensions.PlatformAbstractions": "1.0.0-rc2-16530"
},
"frameworks": {
"net451": { },

View file

@ -249,18 +249,6 @@ namespace Microsoft.DotNet.Tools.Compiler
}
compilerArgs.Add($"--resource:\"{depsJsonFile},{context.ProjectFile.Name}.deps.json\"");
var refsFolder = Path.Combine(outputPath, "refs");
if (Directory.Exists(refsFolder))
{
Directory.Delete(refsFolder, true);
}
Directory.CreateDirectory(refsFolder);
foreach (var reference in references)
{
File.Copy(reference, Path.Combine(refsFolder, Path.GetFileName(reference)));
}
}
if (!AddNonCultureResources(context.ProjectFile, compilerArgs, intermediateOutputPath))

View file

@ -133,6 +133,11 @@ namespace Microsoft.DotNet.Tools.Publish
PublishFiles(export.RuntimeAssemblies, outputPath, nativeSubdirectories: false);
PublishFiles(export.NativeLibraries, outputPath, nativeSubdirectories);
PublishFiles(export.RuntimeAssets, outputPath);
if (options.PreserveCompilationContext.GetValueOrDefault())
{
PublishRefs(export, outputPath);
}
}
CopyContents(context, outputPath);
@ -151,6 +156,26 @@ namespace Microsoft.DotNet.Tools.Publish
return true;
}
private static void PublishRefs(LibraryExport export, string outputPath)
{
var refsPath = Path.Combine(outputPath, "refs");
if (!Directory.Exists(refsPath))
{
Directory.CreateDirectory(refsPath);
}
// Do not copy compilation assembly if it's in runtime assemblies
var runtimeAssemblies = new HashSet<LibraryAsset>(export.RuntimeAssemblies);
foreach (var compilationAssembly in export.CompilationAssemblies)
{
if (!runtimeAssemblies.Contains(compilationAssembly))
{
var destFileName = Path.Combine(refsPath, Path.GetFileName(compilationAssembly.ResolvedPath));
File.Copy(compilationAssembly.ResolvedPath, destFileName, overwrite: true);
}
}
}
private static int PublishHost(ProjectContext context, string outputPath)
{
if (context.TargetFramework.IsDesktop())

View file

@ -0,0 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<packageSources>
<!--To inherit the global NuGet package sources remove the <clear/> line below -->
<clear />
<add key="dotnet-core" value="https://www.myget.org/F/dotnet-core/api/v3/index.json" />
<add key="nugetbuild" value="https://www.myget.org/F/nugetbuild/api/v3/index.json" />
<add key="AspNetCIDev" value="https://www.myget.org/F/aspnetcidev/api/v3/index.json" />
<add key="roslyn-nightly" value="https://www.myget.org/F/roslyn-nightly/api/v3/index.json" />
<add key="api.nuget.org" value="https://api.nuget.org/v3/index.json" />
<add key="dotnet-corefxlab" value="https://www.myget.org/F/dotnet-corefxlab/api/v3/index.json" />
<add key="corefxlab" value="https://www.myget.org/F/netcore-package-prototyping/api/v3/index.json" />
<add key="corert" value="https://www.myget.org/F/dotnet/api/v2" />
<add key="dotnet-buildtools" value="https://www.myget.org/F/dotnet-buildtools/api/v3/index.json" />
<add key="fsharp-daily" value="https://www.myget.org/F/fsharp-daily/api/v3/index.json" />
</packageSources>
<activePackageSource>
<add key="AspNetCIDev" value="https://www.myget.org/F/aspnetcidev/api/v3/index.json" />
</activePackageSource>
</configuration>

View file

@ -0,0 +1,17 @@
// 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;
using System.Diagnostics;
namespace TestApp
{
public class Program
{
public static int Main(string[] args)
{
Console.WriteLine(TestLibrary.Helper.GetMessage());
return 100;
}
}
}

View file

@ -0,0 +1,23 @@
{
"version": "1.0.0-*",
"compilationOptions": {
"emitEntryPoint": true,
"preserveCompilationContext": true
},
"dependencies": {
"TestLibrary": "1.0.0-*",
"NETStandard.Library": "1.0.0-rc2-23704",
"Microsoft.NETCore.Platforms": "1.0.1-rc2-23704"
},
"frameworks": {
"dnxcore50": { }
},
"scripts": {
"prepublish" : ["echo prepublish_output ?%publish:ProjectPath%? ?%publish:Configuration%? ?%publish:OutputPath%? ?%publish:Framework%? ?%publish:Runtime%?"],
"postpublish" : ["echo postpublish_output ?%publish:ProjectPath%? ?%publish:Configuration%? ?%publish:OutputPath%? ?%publish:Framework%? ?%publish:Runtime%?"]
}
}

View file

@ -169,6 +169,37 @@ namespace Microsoft.DotNet.Tools.Publish.Tests
publishCommand.GetOutputDirectory().Should().HaveFile("Newtonsoft.Json.dll");
}
[Fact]
public void RefsPublishTest()
{
// create unique directories in the 'temp' folder
var root = Temp.CreateDirectory();
root.CopyFile(Path.Combine(_testProjectsRoot, "global.json"));
var testAppDir = root.CreateDirectory("TestAppCompilationContext");
var testLibDir = root.CreateDirectory("TestLibrary");
// copy projects to the temp dir
CopyProjectToTempDir(Path.Combine(_testProjectsRoot, "TestAppCompilationContext"), testAppDir);
CopyProjectToTempDir(Path.Combine(_testProjectsRoot, "TestLibrary"), testLibDir);
RunRestore(testAppDir.Path);
RunRestore(testLibDir.Path);
var testProject = GetProjectPath(testAppDir);
var publishCommand = new PublishCommand(testProject);
publishCommand.Execute().Should().Pass();
publishCommand.GetOutputDirectory().Should().HaveFile("TestAppCompilationContext.dll");
publishCommand.GetOutputDirectory().Should().HaveFile("TestLibrary.dll");
var refsDirectory = new DirectoryInfo(Path.Combine(publishCommand.GetOutputDirectory().FullName, "refs"));
// Should have compilation time assemblies
refsDirectory.Should().HaveFile("System.IO.dll");
// Libraries in which lib==ref should be deduped
refsDirectory.Should().NotHaveFile("TestLibrary.dll");
}
[Fact]
public void CompilationFailedTest()
{