Skip to content

Commit

Permalink
Merge pull request #5356 from cston/ng-2
Browse files Browse the repository at this point in the history
Use NuGetPackageResolver in InteractiveHost

- Use resolver in InteractiveHost.Service
- Change reference syntax to #r "nuget:name/version"
- Use local cache only for resolving packages
  • Loading branch information
cston committed Sep 23, 2015
2 parents b9dd948 + 7a5cb9d commit a90e0e6
Show file tree
Hide file tree
Showing 14 changed files with 361 additions and 92 deletions.
41 changes: 41 additions & 0 deletions src/EditorFeatures/Test/project.lock.json
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,14 @@
"lib/net40/Moq.dll": {}
}
},
"Newtonsoft.Json/6.0.4": {
"compile": {
"lib/net45/Newtonsoft.Json.dll": {}
},
"runtime": {
"lib/net45/Newtonsoft.Json.dll": {}
}
},
"System.AppContext/4.0.0": {
"dependencies": {
"System.Runtime": "[4.0.0, )"
Expand Down Expand Up @@ -370,6 +378,14 @@
"lib/net40/Moq.dll": {}
}
},
"Newtonsoft.Json/6.0.4": {
"compile": {
"lib/net45/Newtonsoft.Json.dll": {}
},
"runtime": {
"lib/net45/Newtonsoft.Json.dll": {}
}
},
"System.AppContext/4.0.0": {
"dependencies": {
"System.Runtime": "[4.0.0, )"
Expand Down Expand Up @@ -790,6 +806,31 @@
"package/services/metadata/core-properties/98e2d674c8ec4e5fbda07a9e01280647.psmdcp"
]
},
"Newtonsoft.Json/6.0.4": {
"sha512": "FyQLmEpjsCrEP+znauLDGAi+h6i9YnaMkITlfIoiM4RYyX3nki306bTHsr/0okiIvIc7BJhQTbOAIZVocccFUw==",
"type": "Package",
"files": [
"[Content_Types].xml",
"_rels/.rels",
"lib/net20/Newtonsoft.Json.dll",
"lib/net20/Newtonsoft.Json.xml",
"lib/net35/Newtonsoft.Json.dll",
"lib/net35/Newtonsoft.Json.xml",
"lib/net40/Newtonsoft.Json.dll",
"lib/net40/Newtonsoft.Json.xml",
"lib/net45/Newtonsoft.Json.dll",
"lib/net45/Newtonsoft.Json.xml",
"lib/netcore45/Newtonsoft.Json.dll",
"lib/netcore45/Newtonsoft.Json.xml",
"lib/portable-net40+sl5+wp80+win8+wpa81/Newtonsoft.Json.dll",
"lib/portable-net40+sl5+wp80+win8+wpa81/Newtonsoft.Json.xml",
"lib/portable-net45+wp80+win8+wpa81/Newtonsoft.Json.dll",
"lib/portable-net45+wp80+win8+wpa81/Newtonsoft.Json.xml",
"Newtonsoft.Json.nuspec",
"package/services/metadata/core-properties/87a0a4e28d50417ea282e20f81bc6477.psmdcp",
"tools/install.ps1"
]
},
"System.AppContext/4.0.0": {
"sha512": "gUoYgAWDC3+xhKeU5KSLbYDhTdBYk9GssrMSCcWUADzOglW+s0AmwVhOUGt2tL5xUl7ZXoYTPdA88zCgKrlG0A==",
"type": "Package",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,6 @@
<Compile Include="Extensibility\Interactive\InteractiveEvaluator.cs" />
<Compile Include="Extensibility\Interactive\InteractiveMetadataReferenceResolver.cs" />
<Compile Include="Extensibility\Interactive\CSharpVBInteractiveCommandContentTypes.cs" />
<Compile Include="Extensibility\Interactive\NuGetPackageResolverImpl.cs" />
<Compile Include="Implementation\Completion\InteractiveCommandCompletionService.cs" />
<Compile Include="Implementation\Completion\Presentation\CompletionPresenter.cs" />
<Compile Include="Implementation\Interactive\InertClassifierProvider.cs" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@
using Roslyn.Utilities;

using RuntimeMetadataReferenceResolver = WORKSPACES::Microsoft.CodeAnalysis.Scripting.Hosting.RuntimeMetadataReferenceResolver;
using NuGetPackageResolver = WORKSPACES::Microsoft.CodeAnalysis.Scripting.Hosting.NuGetPackageResolver;
using GacFileResolver = WORKSPACES::Microsoft.CodeAnalysis.Scripting.Hosting.GacFileResolver;

namespace Microsoft.CodeAnalysis.Interactive
Expand Down Expand Up @@ -166,9 +165,13 @@ public void Initialize(Type replServiceProviderType)

private MetadataReferenceResolver CreateMetadataReferenceResolver(ImmutableArray<string> searchPaths, string baseDirectory)
{
var userProfilePath = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile);
var packagesDirectory = string.IsNullOrEmpty(userProfilePath) ?
null :
Path.Combine(userProfilePath, Path.Combine(".nuget", "packages"));
return new RuntimeMetadataReferenceResolver(
new RelativePathResolver(searchPaths, baseDirectory),
null, // TODO
string.IsNullOrEmpty(packagesDirectory) ? null : new NuGetPackageResolverImpl(packagesDirectory),
new GacFileResolver(
architectures: GacFileResolver.Default.Architectures, // TODO (tomat)
preferredCulture: CultureInfo.CurrentCulture), // TODO (tomat)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,23 @@
using System.Diagnostics;
using System.IO;
using System.Reflection;
using NuGetPackageResolver = WORKSPACES::Microsoft.CodeAnalysis.Scripting.Hosting.NuGetPackageResolver;

namespace Microsoft.CodeAnalysis.Editor.Interactive
namespace Microsoft.CodeAnalysis.Interactive
{
internal sealed class NuGetPackageResolverImpl : WORKSPACES::Microsoft.CodeAnalysis.Scripting.Hosting.NuGetPackageResolver
internal sealed class NuGetPackageResolverImpl : NuGetPackageResolver
{
private const string ProjectJsonFramework = "net46";
private const string ProjectLockJsonFramework = ".NETFramework,Version=v4.6";
private const string EmptyNuGetConfig =
@"<?xml version=""1.0"" encoding=""utf-8""?>
<configuration>
<packageRestore>
<add key=""enabled"" value=""True"" />
<add key=""automatic"" value=""False"" />
</packageRestore>
<packageSources/>
</configuration>";

private readonly string _packagesDirectory;
private readonly Action<ProcessStartInfo> _restore;
Expand All @@ -28,35 +38,39 @@ internal NuGetPackageResolverImpl(string packagesDirectory, Action<ProcessStartI
_restore = restore ?? NuGetRestore;
}

internal override ImmutableArray<string> ResolveNuGetPackage(string reference)
internal new static bool TryParsePackageReference(string reference, out string name, out string version)
{
string packageName;
string packageVersion;
if (!ParsePackageReference(reference, out packageName, out packageVersion))
{
return default(ImmutableArray<string>);
}
return NuGetPackageResolver.TryParsePackageReference(reference, out name, out version);
}

internal override ImmutableArray<string> ResolveNuGetPackage(string packageName, string packageVersion)
{
try
{
var tempPath = PathUtilities.CombineAbsoluteAndRelativePaths(Path.GetTempPath(), Guid.NewGuid().ToString("D"));
var tempPath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString("D"));
var tempDir = Directory.CreateDirectory(tempPath);
try
{
// Create project.json.
var projectJson = PathUtilities.CombineAbsoluteAndRelativePaths(tempPath, "project.json");
using (var stream = File.OpenWrite(projectJson))
var projectJsonPath = Path.Combine(tempPath, "project.json");
using (var stream = File.OpenWrite(projectJsonPath))
using (var writer = new StreamWriter(stream))
{
WriteProjectJson(writer, packageName, packageVersion);
}

// Run "nuget.exe restore project.json" to generate project.lock.json.
NuGetRestore(projectJson);
// Create nuget.config with no package sources so restore
// uses the local cache only, no downloading.
var configPath = Path.Combine(tempPath, "nuget.config");
File.WriteAllText(configPath, EmptyNuGetConfig);

// Run "nuget.exe restore project.json -configfile nuget.config"
// to generate project.lock.json.
NuGetRestore(projectJsonPath, configPath);

// Read the references from project.lock.json.
var projectLockJson = PathUtilities.CombineAbsoluteAndRelativePaths(tempPath, "project.lock.json");
using (var stream = File.OpenRead(projectLockJson))
var projectLockJsonPath = Path.Combine(tempPath, "project.lock.json");
using (var stream = File.OpenRead(projectLockJsonPath))
using (var reader = new StreamReader(stream))
{
return ReadProjectLockJson(_packagesDirectory, reader);
Expand All @@ -76,25 +90,6 @@ internal override ImmutableArray<string> ResolveNuGetPackage(string reference)
return default(ImmutableArray<string>);
}

/// <summary>
/// Syntax is "id/version", matching references in project.lock.json.
/// </summary>
internal static bool ParsePackageReference(string reference, out string name, out string version)
{
var parts = reference.Split('/');
if ((parts.Length == 2) &&
(parts[0].Length > 0) &&
(parts[1].Length > 0))
{
name = parts[0];
version = parts[1];
return true;
}
name = null;
version = null;
return false;
}

/// <summary>
/// Generate a project.json file with the packages as "dependencies".
/// </summary>
Expand Down Expand Up @@ -139,16 +134,22 @@ internal static ImmutableArray<string> ReadProjectLockJson(string packagesDirect
{
foreach (var package in (JObject)target.Value)
{
var packageRoot = PathUtilities.CombineAbsoluteAndRelativePaths(packagesDirectory, package.Key);
var packageRoot = Path.Combine(packagesDirectory, package.Key);
var runtime = (JObject)GetPropertyValue((JObject)package.Value, "runtime");
if (runtime == null)
{
continue;
}
foreach (var item in runtime)
{
var path = PathUtilities.CombinePossiblyRelativeAndRelativePaths(packageRoot, item.Key);
builder.Add(path);
var relativePath = item.Key;
// Ignore placeholder "_._" files.
var name = Path.GetFileName(relativePath);
if (string.Equals(name, "_._", StringComparison.InvariantCulture))
{
continue;
}
builder.Add(Path.Combine(packageRoot, relativePath));
}
}
break;
Expand All @@ -164,17 +165,17 @@ private static JToken GetPropertyValue(JObject obj, string propertyName)
return value;
}

private void NuGetRestore(string projectJsonPath)
private void NuGetRestore(string projectJsonPath, string configPath)
{
// Load nuget.exe from same directory as current assembly.
var nugetExePath = PathUtilities.CombineAbsoluteAndRelativePaths(
PathUtilities.GetDirectoryName(
var nugetExePath = Path.Combine(
Path.GetDirectoryName(
CorLightup.Desktop.GetAssemblyLocation(typeof(NuGetPackageResolverImpl).GetTypeInfo().Assembly)),
"nuget.exe");
var startInfo = new ProcessStartInfo()
{
FileName = nugetExePath,
Arguments = $"restore \"{projectJsonPath}\" -PackagesDirectory \"{_packagesDirectory}\"",
Arguments = $"restore \"{projectJsonPath}\" -ConfigFile \"{configPath}\" -PackagesDirectory \"{_packagesDirectory}\"",
CreateNoWindow = true,
UseShellExecute = false,
RedirectStandardOutput = true,
Expand Down
1 change: 1 addition & 0 deletions src/Interactive/Features/InteractiveFeatures.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@
<Compile Include="Interactive\Core\HostObject\SearchPaths.cs" />
<Compile Include="Interactive\Core\SerializableAssemblyLoadResult.cs" />
<Compile Include="Interactive\Core\HostObject\SynchronizedVersionedList.cs" />
<Compile Include="Interactive\Core\NuGetPackageResolverImpl.cs" />
</ItemGroup>
<ItemGroup>
<Compile Include="Interactive\Core\InteractiveHost.LazyRemoteService.cs" />
Expand Down
1 change: 1 addition & 0 deletions src/Interactive/Features/project.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
{
"dependencies": {
"Microsoft.Composition": "1.0.27",
"Newtonsoft.Json": "6.0.4",
"System.Collections": "4.0.10",
"System.Diagnostics.Debug": "4.0.10",
"System.Globalization": "4.0.10",
Expand Down
34 changes: 34 additions & 0 deletions src/Interactive/Features/project.lock.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,14 @@
"lib/net45/_._": {}
}
},
"Newtonsoft.Json/6.0.4": {
"compile": {
"lib/net45/Newtonsoft.Json.dll": {}
},
"runtime": {
"lib/net45/Newtonsoft.Json.dll": {}
}
},
"System.AppContext/4.0.0": {
"dependencies": {
"System.Runtime": "[4.0.0, )"
Expand Down Expand Up @@ -377,6 +385,31 @@
"runtimes/aot/lib/netcore50/System.Xml.Serialization.dll"
]
},
"Newtonsoft.Json/6.0.4": {
"sha512": "FyQLmEpjsCrEP+znauLDGAi+h6i9YnaMkITlfIoiM4RYyX3nki306bTHsr/0okiIvIc7BJhQTbOAIZVocccFUw==",
"type": "Package",
"files": [
"[Content_Types].xml",
"_rels/.rels",
"lib/net20/Newtonsoft.Json.dll",
"lib/net20/Newtonsoft.Json.xml",
"lib/net35/Newtonsoft.Json.dll",
"lib/net35/Newtonsoft.Json.xml",
"lib/net40/Newtonsoft.Json.dll",
"lib/net40/Newtonsoft.Json.xml",
"lib/net45/Newtonsoft.Json.dll",
"lib/net45/Newtonsoft.Json.xml",
"lib/netcore45/Newtonsoft.Json.dll",
"lib/netcore45/Newtonsoft.Json.xml",
"lib/portable-net40+sl5+wp80+win8+wpa81/Newtonsoft.Json.dll",
"lib/portable-net40+sl5+wp80+win8+wpa81/Newtonsoft.Json.xml",
"lib/portable-net45+wp80+win8+wpa81/Newtonsoft.Json.dll",
"lib/portable-net45+wp80+win8+wpa81/Newtonsoft.Json.xml",
"Newtonsoft.Json.nuspec",
"package/services/metadata/core-properties/87a0a4e28d50417ea282e20f81bc6477.psmdcp",
"tools/install.ps1"
]
},
"System.AppContext/4.0.0": {
"sha512": "gUoYgAWDC3+xhKeU5KSLbYDhTdBYk9GssrMSCcWUADzOglW+s0AmwVhOUGt2tL5xUl7ZXoYTPdA88zCgKrlG0A==",
"type": "Package",
Expand Down Expand Up @@ -1164,6 +1197,7 @@
"projectFileDependencyGroups": {
"": [
"Microsoft.Composition >= 1.0.27",
"Newtonsoft.Json >= 6.0.4",
"System.Collections >= 4.0.10",
"System.Diagnostics.Debug >= 4.0.10",
"System.Globalization >= 4.0.10",
Expand Down
41 changes: 41 additions & 0 deletions src/Interactive/Host/project.lock.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,14 @@
"lib/net45/_._": {}
}
},
"Newtonsoft.Json/6.0.4": {
"compile": {
"lib/net45/Newtonsoft.Json.dll": {}
},
"runtime": {
"lib/net45/Newtonsoft.Json.dll": {}
}
},
"System.AppContext/4.0.0": {
"dependencies": {
"System.Runtime": "[4.0.0, )"
Expand Down Expand Up @@ -287,6 +295,14 @@
"lib/net45/_._": {}
}
},
"Newtonsoft.Json/6.0.4": {
"compile": {
"lib/net45/Newtonsoft.Json.dll": {}
},
"runtime": {
"lib/net45/Newtonsoft.Json.dll": {}
}
},
"System.AppContext/4.0.0": {
"dependencies": {
"System.Runtime": "[4.0.0, )"
Expand Down Expand Up @@ -636,6 +652,31 @@
"runtimes/aot/lib/netcore50/System.Xml.Serialization.dll"
]
},
"Newtonsoft.Json/6.0.4": {
"sha512": "FyQLmEpjsCrEP+znauLDGAi+h6i9YnaMkITlfIoiM4RYyX3nki306bTHsr/0okiIvIc7BJhQTbOAIZVocccFUw==",
"type": "Package",
"files": [
"[Content_Types].xml",
"_rels/.rels",
"lib/net20/Newtonsoft.Json.dll",
"lib/net20/Newtonsoft.Json.xml",
"lib/net35/Newtonsoft.Json.dll",
"lib/net35/Newtonsoft.Json.xml",
"lib/net40/Newtonsoft.Json.dll",
"lib/net40/Newtonsoft.Json.xml",
"lib/net45/Newtonsoft.Json.dll",
"lib/net45/Newtonsoft.Json.xml",
"lib/netcore45/Newtonsoft.Json.dll",
"lib/netcore45/Newtonsoft.Json.xml",
"lib/portable-net40+sl5+wp80+win8+wpa81/Newtonsoft.Json.dll",
"lib/portable-net40+sl5+wp80+win8+wpa81/Newtonsoft.Json.xml",
"lib/portable-net45+wp80+win8+wpa81/Newtonsoft.Json.dll",
"lib/portable-net45+wp80+win8+wpa81/Newtonsoft.Json.xml",
"Newtonsoft.Json.nuspec",
"package/services/metadata/core-properties/87a0a4e28d50417ea282e20f81bc6477.psmdcp",
"tools/install.ps1"
]
},
"System.AppContext/4.0.0": {
"sha512": "gUoYgAWDC3+xhKeU5KSLbYDhTdBYk9GssrMSCcWUADzOglW+s0AmwVhOUGt2tL5xUl7ZXoYTPdA88zCgKrlG0A==",
"type": "Package",
Expand Down
Loading

0 comments on commit a90e0e6

Please sign in to comment.