2015-11-16 11:21:57 -08:00
|
|
|
// 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.
|
|
|
|
|
2015-10-28 02:21:00 -07:00
|
|
|
using System;
|
2015-10-13 14:31:29 -07:00
|
|
|
using System.Collections.Generic;
|
|
|
|
using System.IO;
|
|
|
|
using System.Linq;
|
2016-03-30 14:51:43 -07:00
|
|
|
using System.Text;
|
2015-11-27 16:19:54 -08:00
|
|
|
using Microsoft.DotNet.ProjectModel.Graph;
|
|
|
|
using Microsoft.DotNet.ProjectModel.Resolution;
|
2015-10-21 12:59:44 -07:00
|
|
|
using Microsoft.Extensions.Internal;
|
2016-04-08 08:51:51 -07:00
|
|
|
using Microsoft.Extensions.PlatformAbstractions;
|
2015-10-13 14:31:29 -07:00
|
|
|
using NuGet.Frameworks;
|
|
|
|
|
2015-11-27 16:19:54 -08:00
|
|
|
namespace Microsoft.DotNet.ProjectModel
|
2015-10-13 14:31:29 -07:00
|
|
|
{
|
|
|
|
public class ProjectContextBuilder
|
|
|
|
{
|
2015-10-29 01:35:23 -07:00
|
|
|
private Project Project { get; set; }
|
2015-10-13 14:31:29 -07:00
|
|
|
|
2015-10-29 01:35:23 -07:00
|
|
|
private LockFile LockFile { get; set; }
|
2015-10-13 14:31:29 -07:00
|
|
|
|
2015-10-29 01:35:23 -07:00
|
|
|
private GlobalSettings GlobalSettings { get; set; }
|
2015-10-13 14:31:29 -07:00
|
|
|
|
2015-10-29 01:35:23 -07:00
|
|
|
private NuGetFramework TargetFramework { get; set; }
|
2015-10-13 14:31:29 -07:00
|
|
|
|
2015-10-29 01:35:23 -07:00
|
|
|
private IEnumerable<string> RuntimeIdentifiers { get; set; } = Enumerable.Empty<string>();
|
2015-10-13 14:31:29 -07:00
|
|
|
|
2015-10-29 01:35:23 -07:00
|
|
|
private string RootDirectory { get; set; }
|
2015-10-13 14:31:29 -07:00
|
|
|
|
2015-10-29 01:35:23 -07:00
|
|
|
private string ProjectDirectory { get; set; }
|
2015-10-13 14:31:29 -07:00
|
|
|
|
2015-10-29 01:35:23 -07:00
|
|
|
private string PackagesDirectory { get; set; }
|
2015-11-30 16:08:32 -08:00
|
|
|
|
2015-10-29 01:35:23 -07:00
|
|
|
private string ReferenceAssembliesPath { get; set; }
|
2016-04-08 08:51:51 -07:00
|
|
|
|
2016-03-31 11:15:50 -07:00
|
|
|
private bool IsDesignTime { get; set; }
|
2015-10-29 01:35:23 -07:00
|
|
|
|
2015-11-30 16:08:32 -08:00
|
|
|
private Func<string, Project> ProjectResolver { get; set; }
|
|
|
|
|
|
|
|
private Func<string, LockFile> LockFileResolver { get; set; }
|
|
|
|
|
2016-02-18 01:09:23 -08:00
|
|
|
private ProjectReaderSettings Settings { get; set; } = ProjectReaderSettings.ReadFromEnvironment();
|
2015-12-08 23:22:08 -08:00
|
|
|
|
2015-12-02 23:32:27 -08:00
|
|
|
public ProjectContextBuilder()
|
|
|
|
{
|
|
|
|
ProjectResolver = ResolveProject;
|
|
|
|
LockFileResolver = ResolveLockFile;
|
|
|
|
}
|
|
|
|
|
2015-10-29 01:35:23 -07:00
|
|
|
public ProjectContextBuilder WithLockFile(LockFile lockFile)
|
|
|
|
{
|
|
|
|
LockFile = lockFile;
|
|
|
|
return this;
|
|
|
|
}
|
2015-11-30 16:08:32 -08:00
|
|
|
|
2015-10-29 01:35:23 -07:00
|
|
|
public ProjectContextBuilder WithProject(Project project)
|
|
|
|
{
|
|
|
|
Project = project;
|
|
|
|
return this;
|
|
|
|
}
|
2015-11-30 16:08:32 -08:00
|
|
|
|
2015-10-29 01:35:23 -07:00
|
|
|
public ProjectContextBuilder WithProjectDirectory(string projectDirectory)
|
|
|
|
{
|
|
|
|
ProjectDirectory = projectDirectory;
|
|
|
|
return this;
|
|
|
|
}
|
2015-11-30 16:08:32 -08:00
|
|
|
|
2015-10-29 01:35:23 -07:00
|
|
|
public ProjectContextBuilder WithTargetFramework(NuGetFramework targetFramework)
|
|
|
|
{
|
|
|
|
TargetFramework = targetFramework;
|
|
|
|
return this;
|
|
|
|
}
|
2015-11-30 16:08:32 -08:00
|
|
|
|
2015-10-29 01:35:23 -07:00
|
|
|
public ProjectContextBuilder WithTargetFramework(string targetFramework)
|
|
|
|
{
|
|
|
|
TargetFramework = NuGetFramework.Parse(targetFramework);
|
|
|
|
return this;
|
|
|
|
}
|
|
|
|
|
|
|
|
public ProjectContextBuilder WithRuntimeIdentifiers(IEnumerable<string> runtimeIdentifiers)
|
|
|
|
{
|
|
|
|
RuntimeIdentifiers = runtimeIdentifiers;
|
|
|
|
return this;
|
|
|
|
}
|
|
|
|
|
|
|
|
public ProjectContextBuilder WithReferenceAssembliesPath(string referenceAssembliesPath)
|
|
|
|
{
|
|
|
|
ReferenceAssembliesPath = referenceAssembliesPath;
|
|
|
|
return this;
|
|
|
|
}
|
2015-11-30 16:08:32 -08:00
|
|
|
|
2015-10-29 01:35:23 -07:00
|
|
|
public ProjectContextBuilder WithPackagesDirectory(string packagesDirectory)
|
|
|
|
{
|
|
|
|
PackagesDirectory = packagesDirectory;
|
|
|
|
return this;
|
|
|
|
}
|
2015-11-30 16:08:32 -08:00
|
|
|
|
2015-10-29 01:35:23 -07:00
|
|
|
public ProjectContextBuilder WithRootDirectory(string rootDirectory)
|
|
|
|
{
|
|
|
|
RootDirectory = rootDirectory;
|
|
|
|
return this;
|
|
|
|
}
|
2015-10-13 14:31:29 -07:00
|
|
|
|
2015-11-30 16:08:32 -08:00
|
|
|
public ProjectContextBuilder WithProjectResolver(Func<string, Project> projectResolver)
|
|
|
|
{
|
|
|
|
ProjectResolver = projectResolver;
|
|
|
|
return this;
|
|
|
|
}
|
|
|
|
|
|
|
|
public ProjectContextBuilder WithLockFileResolver(Func<string, LockFile> lockFileResolver)
|
|
|
|
{
|
|
|
|
LockFileResolver = lockFileResolver;
|
|
|
|
return this;
|
|
|
|
}
|
|
|
|
|
2015-12-09 00:47:57 -08:00
|
|
|
public ProjectContextBuilder WithReaderSettings(ProjectReaderSettings settings)
|
2015-12-08 23:22:08 -08:00
|
|
|
{
|
|
|
|
Settings = settings;
|
|
|
|
return this;
|
|
|
|
}
|
2016-04-08 08:51:51 -07:00
|
|
|
|
2016-03-31 11:15:50 -07:00
|
|
|
public ProjectContextBuilder AsDesignTime()
|
|
|
|
{
|
|
|
|
IsDesignTime = true;
|
|
|
|
return this;
|
|
|
|
}
|
2015-12-08 23:22:08 -08:00
|
|
|
|
2015-12-02 23:32:27 -08:00
|
|
|
public IEnumerable<ProjectContext> BuildAllTargets()
|
2015-10-13 14:31:29 -07:00
|
|
|
{
|
2015-12-02 23:32:27 -08:00
|
|
|
ProjectDirectory = Project?.ProjectDirectory ?? ProjectDirectory;
|
|
|
|
EnsureProjectLoaded();
|
|
|
|
LockFile = LockFile ?? LockFileResolver(ProjectDirectory);
|
2015-11-30 16:08:32 -08:00
|
|
|
|
2015-12-02 23:32:27 -08:00
|
|
|
if (LockFile != null)
|
|
|
|
{
|
|
|
|
foreach (var target in LockFile.Targets)
|
|
|
|
{
|
|
|
|
yield return new ProjectContextBuilder()
|
|
|
|
.WithProject(Project)
|
|
|
|
.WithLockFile(LockFile)
|
|
|
|
.WithTargetFramework(target.TargetFramework)
|
|
|
|
.WithRuntimeIdentifiers(new[] { target.RuntimeIdentifier })
|
|
|
|
.Build();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public ProjectContext Build()
|
|
|
|
{
|
2016-03-30 14:51:43 -07:00
|
|
|
var diagnostics = new List<DiagnosticMessage>();
|
|
|
|
|
2015-10-13 14:31:29 -07:00
|
|
|
ProjectDirectory = Project?.ProjectDirectory ?? ProjectDirectory;
|
|
|
|
|
2016-03-17 11:45:13 -07:00
|
|
|
if (GlobalSettings == null && ProjectDirectory != null)
|
2015-10-13 14:31:29 -07:00
|
|
|
{
|
2015-10-21 12:59:44 -07:00
|
|
|
RootDirectory = ProjectRootResolver.ResolveRootDirectory(ProjectDirectory);
|
|
|
|
|
2015-10-13 14:31:29 -07:00
|
|
|
GlobalSettings globalSettings;
|
2015-10-21 12:59:44 -07:00
|
|
|
if (GlobalSettings.TryGetGlobalSettings(RootDirectory, out globalSettings))
|
2015-10-13 14:31:29 -07:00
|
|
|
{
|
|
|
|
GlobalSettings = globalSettings;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
RootDirectory = GlobalSettings?.DirectoryPath ?? RootDirectory;
|
2015-10-29 01:35:23 -07:00
|
|
|
PackagesDirectory = PackagesDirectory ?? PackageDependencyProvider.ResolvePackagesPath(RootDirectory, GlobalSettings);
|
2015-12-25 20:10:26 -08:00
|
|
|
ReferenceAssembliesPath = ReferenceAssembliesPath ?? FrameworkReferenceResolver.GetDefaultReferenceAssembliesPath();
|
2016-01-24 11:05:31 -08:00
|
|
|
var frameworkReferenceResolver = new FrameworkReferenceResolver(ReferenceAssembliesPath);
|
2015-10-13 14:31:29 -07:00
|
|
|
|
|
|
|
LockFileLookup lockFileLookup = null;
|
|
|
|
EnsureProjectLoaded();
|
|
|
|
|
2016-03-30 14:51:43 -07:00
|
|
|
ReadLockFile(diagnostics);
|
2015-10-13 14:31:29 -07:00
|
|
|
|
|
|
|
var validLockFile = true;
|
|
|
|
string lockFileValidationMessage = null;
|
|
|
|
|
|
|
|
if (LockFile != null)
|
|
|
|
{
|
2016-03-17 11:45:13 -07:00
|
|
|
if (Project != null)
|
|
|
|
{
|
|
|
|
validLockFile = LockFile.IsValidForProject(Project, out lockFileValidationMessage);
|
|
|
|
}
|
2015-10-13 14:31:29 -07:00
|
|
|
|
|
|
|
lockFileLookup = new LockFileLookup(LockFile);
|
|
|
|
}
|
|
|
|
|
2015-10-21 12:59:44 -07:00
|
|
|
var libraries = new Dictionary<LibraryKey, LibraryDescription>();
|
2016-01-03 08:18:25 -08:00
|
|
|
var projectResolver = new ProjectDependencyProvider(ProjectResolver);
|
2015-10-13 14:31:29 -07:00
|
|
|
|
2016-03-17 11:45:13 -07:00
|
|
|
ProjectDescription mainProject = null;
|
|
|
|
if (Project != null)
|
|
|
|
{
|
|
|
|
mainProject = projectResolver.GetDescription(TargetFramework, Project, targetLibrary: null);
|
2015-10-13 14:31:29 -07:00
|
|
|
|
2016-03-17 11:45:13 -07:00
|
|
|
// Add the main project
|
|
|
|
libraries.Add(new LibraryKey(mainProject.Identity.Name), mainProject);
|
|
|
|
}
|
2015-10-13 14:31:29 -07:00
|
|
|
|
2016-04-08 08:51:51 -07:00
|
|
|
LibraryRange? platformDependency = null;
|
|
|
|
if (mainProject != null)
|
|
|
|
{
|
|
|
|
platformDependency = mainProject.Dependencies
|
|
|
|
.Where(d => d.Type.Equals(LibraryDependencyType.Platform))
|
|
|
|
.Cast<LibraryRange?>()
|
|
|
|
.FirstOrDefault();
|
|
|
|
}
|
|
|
|
bool isPortable = platformDependency != null || TargetFramework.IsDesktop();
|
|
|
|
|
2015-10-13 14:31:29 -07:00
|
|
|
LockFileTarget target = null;
|
2016-04-08 16:27:09 -07:00
|
|
|
LibraryDescription platformLibrary = null;
|
|
|
|
|
2015-10-13 14:31:29 -07:00
|
|
|
if (lockFileLookup != null)
|
|
|
|
{
|
2016-04-08 08:51:51 -07:00
|
|
|
target = SelectTarget(LockFile, isPortable);
|
2015-10-13 14:31:29 -07:00
|
|
|
if (target != null)
|
|
|
|
{
|
2016-03-23 15:26:36 -07:00
|
|
|
var nugetPackageResolver = new PackageDependencyProvider(PackagesDirectory, frameworkReferenceResolver);
|
2016-03-30 14:51:43 -07:00
|
|
|
var msbuildProjectResolver = new MSBuildDependencyProvider(Project, ProjectResolver);
|
2016-03-23 15:26:36 -07:00
|
|
|
ScanLibraries(target, lockFileLookup, libraries, msbuildProjectResolver, nugetPackageResolver, projectResolver);
|
2016-04-08 16:27:09 -07:00
|
|
|
|
|
|
|
if (platformDependency != null)
|
|
|
|
{
|
|
|
|
platformLibrary = libraries[new LibraryKey(platformDependency.Value.Name)];
|
|
|
|
}
|
2015-10-13 14:31:29 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-04-08 08:51:51 -07:00
|
|
|
string runtime;
|
|
|
|
if (TargetFramework.IsDesktop())
|
|
|
|
{
|
|
|
|
var legacyRuntime = PlatformServices.Default.Runtime.GetLegacyRestoreRuntimeIdentifier();
|
|
|
|
if (RuntimeIdentifiers.Contains(legacyRuntime))
|
|
|
|
{
|
|
|
|
runtime = legacyRuntime;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
runtime = RuntimeIdentifiers.FirstOrDefault();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
runtime = target?.RuntimeIdentifier;
|
|
|
|
}
|
|
|
|
|
2015-10-13 14:31:29 -07:00
|
|
|
var referenceAssemblyDependencyResolver = new ReferenceAssemblyDependencyResolver(frameworkReferenceResolver);
|
2015-10-28 02:21:00 -07:00
|
|
|
bool requiresFrameworkAssemblies;
|
2015-10-13 14:31:29 -07:00
|
|
|
|
|
|
|
// Resolve the dependencies
|
2015-10-28 02:21:00 -07:00
|
|
|
ResolveDependencies(libraries, referenceAssemblyDependencyResolver, out requiresFrameworkAssemblies);
|
2015-10-13 14:31:29 -07:00
|
|
|
|
2015-10-17 07:34:04 -07:00
|
|
|
// REVIEW: Should this be in NuGet (possibly stored in the lock file?)
|
|
|
|
if (LockFile == null)
|
|
|
|
{
|
|
|
|
diagnostics.Add(new DiagnosticMessage(
|
|
|
|
ErrorCodes.NU1009,
|
2015-11-07 02:24:53 -08:00
|
|
|
$"The expected lock file doesn't exist. Please run \"dotnet restore\" to generate a new lock file.",
|
2015-10-17 07:34:04 -07:00
|
|
|
Path.Combine(Project.ProjectDirectory, LockFile.FileName),
|
|
|
|
DiagnosticMessageSeverity.Error));
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!validLockFile)
|
|
|
|
{
|
|
|
|
diagnostics.Add(new DiagnosticMessage(
|
|
|
|
ErrorCodes.NU1006,
|
2015-11-07 02:24:53 -08:00
|
|
|
$"{lockFileValidationMessage}. Please run \"dotnet restore\" to generate a new lock file.",
|
2015-10-17 07:34:04 -07:00
|
|
|
Path.Combine(Project.ProjectDirectory, LockFile.FileName),
|
|
|
|
DiagnosticMessageSeverity.Warning));
|
|
|
|
}
|
|
|
|
|
2015-11-07 23:53:05 -08:00
|
|
|
if (requiresFrameworkAssemblies)
|
2015-10-28 02:21:00 -07:00
|
|
|
{
|
|
|
|
var frameworkInfo = Project.GetTargetFramework(TargetFramework);
|
2015-11-07 23:53:05 -08:00
|
|
|
|
|
|
|
if (string.IsNullOrEmpty(ReferenceAssembliesPath))
|
|
|
|
{
|
|
|
|
// If there was an attempt to use reference assemblies but they were not installed
|
|
|
|
// report an error
|
|
|
|
diagnostics.Add(new DiagnosticMessage(
|
|
|
|
ErrorCodes.DOTNET1012,
|
|
|
|
$"The reference assemblies directory was not specified. You can set the location using the DOTNET_REFERENCE_ASSEMBLIES_PATH environment variable.",
|
|
|
|
filePath: Project.ProjectFilePath,
|
|
|
|
severity: DiagnosticMessageSeverity.Error,
|
|
|
|
startLine: frameworkInfo.Line,
|
|
|
|
startColumn: frameworkInfo.Column
|
|
|
|
));
|
|
|
|
}
|
|
|
|
else if (!frameworkReferenceResolver.IsInstalled(TargetFramework))
|
|
|
|
{
|
|
|
|
// If there was an attempt to use reference assemblies but they were not installed
|
|
|
|
// report an error
|
|
|
|
diagnostics.Add(new DiagnosticMessage(
|
|
|
|
ErrorCodes.DOTNET1011,
|
|
|
|
$"Framework not installed: {TargetFramework.DotNetFrameworkName} in {ReferenceAssembliesPath}",
|
|
|
|
filePath: Project.ProjectFilePath,
|
|
|
|
severity: DiagnosticMessageSeverity.Error,
|
|
|
|
startLine: frameworkInfo.Line,
|
|
|
|
startColumn: frameworkInfo.Column
|
|
|
|
));
|
|
|
|
}
|
2015-10-28 02:21:00 -07:00
|
|
|
}
|
|
|
|
|
2015-10-17 07:34:04 -07:00
|
|
|
// Create a library manager
|
2016-03-17 11:45:13 -07:00
|
|
|
var libraryManager = new LibraryManager(libraries.Values.ToList(), diagnostics, Project?.ProjectFilePath);
|
2015-10-13 14:31:29 -07:00
|
|
|
|
|
|
|
return new ProjectContext(
|
|
|
|
GlobalSettings,
|
|
|
|
mainProject,
|
2016-04-08 08:51:51 -07:00
|
|
|
platformLibrary,
|
2015-10-13 14:31:29 -07:00
|
|
|
TargetFramework,
|
2016-04-08 08:51:51 -07:00
|
|
|
isPortable,
|
|
|
|
runtime,
|
2015-10-13 14:31:29 -07:00
|
|
|
PackagesDirectory,
|
2016-01-14 11:52:03 -08:00
|
|
|
libraryManager,
|
|
|
|
LockFile);
|
2015-10-13 14:31:29 -07:00
|
|
|
}
|
|
|
|
|
2016-03-30 14:51:43 -07:00
|
|
|
private void ReadLockFile(ICollection<DiagnosticMessage> diagnostics)
|
|
|
|
{
|
|
|
|
try
|
|
|
|
{
|
|
|
|
LockFile = LockFile ?? LockFileResolver(ProjectDirectory);
|
|
|
|
}
|
|
|
|
catch (FileFormatException e)
|
|
|
|
{
|
|
|
|
var lockFilePath = "";
|
|
|
|
if (LockFile != null)
|
|
|
|
{
|
|
|
|
lockFilePath = LockFile.LockFilePath;
|
|
|
|
}
|
|
|
|
else if (Project != null)
|
|
|
|
{
|
|
|
|
lockFilePath = Path.Combine(Project.ProjectDirectory, LockFile.FileName);
|
|
|
|
}
|
|
|
|
|
|
|
|
diagnostics.Add(new DiagnosticMessage(
|
|
|
|
ErrorCodes.DOTNET1014,
|
|
|
|
ComposeMessageFromInnerExceptions(e),
|
|
|
|
lockFilePath,
|
|
|
|
DiagnosticMessageSeverity.Error));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private static string ComposeMessageFromInnerExceptions(Exception exception)
|
|
|
|
{
|
|
|
|
var sb = new StringBuilder();
|
2016-03-30 18:22:35 -07:00
|
|
|
var messages = new HashSet<string>();
|
2016-03-30 14:51:43 -07:00
|
|
|
|
|
|
|
while (exception != null)
|
|
|
|
{
|
2016-03-30 18:22:35 -07:00
|
|
|
messages.Add(exception.Message);
|
2016-03-30 14:51:43 -07:00
|
|
|
exception = exception.InnerException;
|
|
|
|
}
|
|
|
|
|
2016-03-30 18:22:35 -07:00
|
|
|
foreach (var message in messages)
|
|
|
|
{
|
|
|
|
sb.AppendLine(message);
|
|
|
|
}
|
|
|
|
|
2016-03-30 14:51:43 -07:00
|
|
|
return sb.ToString();
|
|
|
|
}
|
|
|
|
|
2015-11-30 16:08:32 -08:00
|
|
|
private void ResolveDependencies(Dictionary<LibraryKey, LibraryDescription> libraries,
|
2015-10-28 02:21:00 -07:00
|
|
|
ReferenceAssemblyDependencyResolver referenceAssemblyDependencyResolver,
|
|
|
|
out bool requiresFrameworkAssemblies)
|
2015-10-13 14:31:29 -07:00
|
|
|
{
|
2016-01-29 01:49:56 -08:00
|
|
|
// Remark: the LibraryType in the key of the given dictionary are all "Unspecified" at the beginning.
|
2015-10-28 02:21:00 -07:00
|
|
|
requiresFrameworkAssemblies = false;
|
2015-11-30 16:08:32 -08:00
|
|
|
|
2016-01-24 11:05:31 -08:00
|
|
|
foreach (var pair in libraries.ToList())
|
2015-10-13 14:31:29 -07:00
|
|
|
{
|
2016-01-24 11:05:31 -08:00
|
|
|
var library = pair.Value;
|
|
|
|
|
|
|
|
// The System.* packages provide placeholders on any non netstandard platform
|
|
|
|
// To make them work seamlessly on those platforms, we fill the gap with a reference
|
|
|
|
// assembly (if available)
|
|
|
|
var package = library as PackageDescription;
|
2016-02-23 02:34:27 -08:00
|
|
|
if (package != null && package.Resolved && !package.CompileTimeAssemblies.Any())
|
2016-01-24 11:05:31 -08:00
|
|
|
{
|
|
|
|
var replacement = referenceAssemblyDependencyResolver.GetDescription(new LibraryRange(library.Identity.Name, LibraryType.ReferenceAssembly), TargetFramework);
|
|
|
|
if (replacement?.Resolved == true)
|
|
|
|
{
|
|
|
|
requiresFrameworkAssemblies = true;
|
|
|
|
|
|
|
|
// Remove the original package reference
|
|
|
|
libraries.Remove(pair.Key);
|
|
|
|
|
2016-01-29 01:49:56 -08:00
|
|
|
// Insert a reference assembly key if there isn't one
|
|
|
|
var key = new LibraryKey(replacement.Identity.Name, LibraryType.ReferenceAssembly);
|
|
|
|
if (!libraries.ContainsKey(key))
|
|
|
|
{
|
|
|
|
libraries[key] = replacement;
|
|
|
|
}
|
2016-01-24 11:05:31 -08:00
|
|
|
}
|
|
|
|
}
|
2016-01-29 01:49:56 -08:00
|
|
|
}
|
2016-01-24 11:05:31 -08:00
|
|
|
|
2016-01-29 01:49:56 -08:00
|
|
|
foreach (var pair in libraries.ToList())
|
|
|
|
{
|
|
|
|
var library = pair.Value;
|
2015-10-13 14:31:29 -07:00
|
|
|
library.Framework = library.Framework ?? TargetFramework;
|
|
|
|
foreach (var dependency in library.Dependencies)
|
|
|
|
{
|
2016-01-29 01:49:56 -08:00
|
|
|
var keyType = dependency.Target == LibraryType.ReferenceAssembly ?
|
|
|
|
LibraryType.ReferenceAssembly :
|
|
|
|
LibraryType.Unspecified;
|
|
|
|
|
2015-10-21 12:59:44 -07:00
|
|
|
var key = new LibraryKey(dependency.Name, keyType);
|
|
|
|
|
2016-01-29 01:49:56 -08:00
|
|
|
LibraryDescription dependencyDescription;
|
|
|
|
if (!libraries.TryGetValue(key, out dependencyDescription))
|
2015-10-13 14:31:29 -07:00
|
|
|
{
|
2016-01-29 01:49:56 -08:00
|
|
|
if (keyType == LibraryType.ReferenceAssembly)
|
2015-10-13 14:31:29 -07:00
|
|
|
{
|
2016-01-29 01:49:56 -08:00
|
|
|
// a dependency is specified to be reference assembly but fail to match
|
|
|
|
// then add a unresolved dependency
|
|
|
|
dependencyDescription = referenceAssemblyDependencyResolver.GetDescription(dependency, TargetFramework) ??
|
|
|
|
UnresolvedDependencyProvider.GetDescription(dependency, TargetFramework);
|
|
|
|
libraries[key] = dependencyDescription;
|
2015-10-13 14:31:29 -07:00
|
|
|
}
|
2016-01-29 01:49:56 -08:00
|
|
|
else if (!libraries.TryGetValue(new LibraryKey(dependency.Name, LibraryType.ReferenceAssembly), out dependencyDescription))
|
2015-10-13 14:31:29 -07:00
|
|
|
{
|
2016-01-29 01:49:56 -08:00
|
|
|
// a dependency which type is unspecified fails to match, then try to find a
|
|
|
|
// reference assembly type dependency
|
|
|
|
dependencyDescription = UnresolvedDependencyProvider.GetDescription(dependency, TargetFramework);
|
|
|
|
libraries[key] = dependencyDescription;
|
2015-10-13 14:31:29 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-01-29 01:49:56 -08:00
|
|
|
dependencyDescription.RequestedRanges.Add(dependency);
|
|
|
|
dependencyDescription.Parents.Add(library);
|
2015-10-13 14:31:29 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-03-31 11:15:50 -07:00
|
|
|
private void ScanLibraries(LockFileTarget target,
|
|
|
|
LockFileLookup lockFileLookup,
|
|
|
|
Dictionary<LibraryKey, LibraryDescription> libraries,
|
|
|
|
MSBuildDependencyProvider msbuildResolver,
|
|
|
|
PackageDependencyProvider packageResolver,
|
|
|
|
ProjectDependencyProvider projectResolver)
|
2015-10-13 14:31:29 -07:00
|
|
|
{
|
|
|
|
foreach (var library in target.Libraries)
|
|
|
|
{
|
2015-10-24 04:32:26 -07:00
|
|
|
LibraryDescription description = null;
|
|
|
|
var type = LibraryType.Unspecified;
|
|
|
|
|
2015-10-13 14:31:29 -07:00
|
|
|
if (string.Equals(library.Type, "project"))
|
|
|
|
{
|
|
|
|
var projectLibrary = lockFileLookup.GetProject(library.Name);
|
|
|
|
|
2015-10-24 04:32:26 -07:00
|
|
|
if (projectLibrary != null)
|
|
|
|
{
|
2016-03-23 15:26:36 -07:00
|
|
|
if (MSBuildDependencyProvider.IsMSBuildProjectLibrary(projectLibrary))
|
|
|
|
{
|
2016-03-31 11:15:50 -07:00
|
|
|
description = msbuildResolver.GetDescription(TargetFramework, projectLibrary, library, IsDesignTime);
|
2016-03-23 15:26:36 -07:00
|
|
|
type = LibraryType.MSBuildProject;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
var path = Path.GetFullPath(Path.Combine(ProjectDirectory, projectLibrary.Path));
|
|
|
|
description = projectResolver.GetDescription(library.Name, path, library, ProjectResolver);
|
|
|
|
type = LibraryType.Project;
|
|
|
|
}
|
2015-10-24 04:32:26 -07:00
|
|
|
}
|
2015-10-13 14:31:29 -07:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
var packageEntry = lockFileLookup.GetPackage(library.Name, library.Version);
|
|
|
|
|
2015-10-24 04:32:26 -07:00
|
|
|
if (packageEntry != null)
|
|
|
|
{
|
2016-01-24 11:05:31 -08:00
|
|
|
description = packageResolver.GetDescription(TargetFramework, packageEntry, library);
|
2015-10-24 04:32:26 -07:00
|
|
|
}
|
2015-10-13 14:31:29 -07:00
|
|
|
|
2015-10-24 04:32:26 -07:00
|
|
|
type = LibraryType.Package;
|
2015-10-13 14:31:29 -07:00
|
|
|
}
|
2015-10-24 04:32:26 -07:00
|
|
|
|
|
|
|
description = description ?? UnresolvedDependencyProvider.GetDescription(new LibraryRange(library.Name, type), target.TargetFramework);
|
|
|
|
|
|
|
|
libraries.Add(new LibraryKey(library.Name), description);
|
2015-10-13 14:31:29 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private void EnsureProjectLoaded()
|
|
|
|
{
|
2016-03-17 11:45:13 -07:00
|
|
|
if (Project == null && ProjectDirectory != null)
|
2015-10-13 14:31:29 -07:00
|
|
|
{
|
2015-11-30 16:08:32 -08:00
|
|
|
Project = ProjectResolver(ProjectDirectory);
|
2016-04-19 19:14:59 -07:00
|
|
|
if (Project == null)
|
|
|
|
{
|
|
|
|
throw new InvalidOperationException($"Could not resolve project at: {ProjectDirectory}. " +
|
|
|
|
$"This could happen when project.lock.json was moved after restore.");
|
|
|
|
}
|
2015-10-13 14:31:29 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-04-08 08:51:51 -07:00
|
|
|
private LockFileTarget SelectTarget(LockFile lockFile, bool isPortable)
|
2015-10-13 14:31:29 -07:00
|
|
|
{
|
2016-04-08 08:51:51 -07:00
|
|
|
if (!isPortable)
|
2015-10-13 14:31:29 -07:00
|
|
|
{
|
2016-04-08 08:51:51 -07:00
|
|
|
foreach (var runtimeIdentifier in RuntimeIdentifiers)
|
2015-10-13 14:31:29 -07:00
|
|
|
{
|
2016-04-08 08:51:51 -07:00
|
|
|
foreach (var scanTarget in lockFile.Targets)
|
2015-10-13 14:31:29 -07:00
|
|
|
{
|
2016-04-08 08:51:51 -07:00
|
|
|
if (Equals(scanTarget.TargetFramework, TargetFramework) && string.Equals(scanTarget.RuntimeIdentifier, runtimeIdentifier, StringComparison.Ordinal))
|
|
|
|
{
|
|
|
|
return scanTarget;
|
|
|
|
}
|
2015-10-13 14:31:29 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
foreach (var scanTarget in lockFile.Targets)
|
|
|
|
{
|
|
|
|
if (Equals(scanTarget.TargetFramework, TargetFramework) && string.IsNullOrEmpty(scanTarget.RuntimeIdentifier))
|
|
|
|
{
|
|
|
|
return scanTarget;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return null;
|
|
|
|
}
|
2015-10-21 12:59:44 -07:00
|
|
|
|
2016-01-03 08:18:25 -08:00
|
|
|
private Project ResolveProject(string projectDirectory)
|
2015-11-30 16:08:32 -08:00
|
|
|
{
|
2016-01-03 08:18:25 -08:00
|
|
|
// TODO: Handle diagnostics
|
2015-11-30 16:08:32 -08:00
|
|
|
Project project;
|
2016-01-03 08:18:25 -08:00
|
|
|
if (ProjectReader.TryGetProject(projectDirectory, out project, diagnostics: null, settings: Settings))
|
2015-11-30 16:08:32 -08:00
|
|
|
{
|
|
|
|
return project;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-12-02 23:32:27 -08:00
|
|
|
private static LockFile ResolveLockFile(string projectDir)
|
|
|
|
{
|
|
|
|
var projectLockJsonPath = Path.Combine(projectDir, LockFile.FileName);
|
|
|
|
return File.Exists(projectLockJsonPath) ?
|
2016-03-31 11:15:50 -07:00
|
|
|
LockFileReader.Read(Path.Combine(projectDir, LockFile.FileName), designTime: false) :
|
2015-12-02 23:32:27 -08:00
|
|
|
null;
|
|
|
|
}
|
|
|
|
|
2015-10-21 12:59:44 -07:00
|
|
|
private struct LibraryKey
|
|
|
|
{
|
|
|
|
public LibraryKey(string name) : this(name, LibraryType.Unspecified)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
public LibraryKey(string name, LibraryType libraryType)
|
|
|
|
{
|
|
|
|
Name = name;
|
|
|
|
LibraryType = libraryType;
|
|
|
|
}
|
|
|
|
|
|
|
|
public string Name { get; }
|
|
|
|
public LibraryType LibraryType { get; }
|
|
|
|
|
|
|
|
public override bool Equals(object obj)
|
|
|
|
{
|
|
|
|
var otherKey = (LibraryKey)obj;
|
|
|
|
|
|
|
|
return string.Equals(otherKey.Name, Name, StringComparison.Ordinal) &&
|
|
|
|
otherKey.LibraryType.Equals(LibraryType);
|
|
|
|
}
|
|
|
|
|
|
|
|
public override int GetHashCode()
|
|
|
|
{
|
|
|
|
var combiner = new HashCodeCombiner();
|
|
|
|
combiner.Add(Name);
|
|
|
|
combiner.Add(LibraryType);
|
|
|
|
|
|
|
|
return combiner.CombinedHash;
|
|
|
|
}
|
2016-03-04 01:17:37 -08:00
|
|
|
|
|
|
|
public override string ToString()
|
|
|
|
{
|
|
|
|
return Name + " " + LibraryType;
|
|
|
|
}
|
2015-10-21 12:59:44 -07:00
|
|
|
}
|
2015-10-13 14:31:29 -07:00
|
|
|
}
|
|
|
|
}
|