Add Dependency Resolution Apis to ProjectContext Abstractions
This commit is contained in:
parent
c20b9ae894
commit
f7932b57a6
|
|
@ -0,0 +1,98 @@
|
||||||
|
// Copyright (c) .NET Foundation. All rights reserved.
|
||||||
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.IO;
|
||||||
|
using Microsoft.DotNet.ProjectModel;
|
||||||
|
using Microsoft.Extensions.ProjectModel.Resolution;
|
||||||
|
using Microsoft.DotNet.Cli.Utils;
|
||||||
|
|
||||||
|
namespace Microsoft.Extensions.ProjectModel
|
||||||
|
{
|
||||||
|
internal class DotNetDependencyProvider
|
||||||
|
{
|
||||||
|
private ProjectContext _context;
|
||||||
|
private List<DependencyDescription> _packageDependencies;
|
||||||
|
private List<ResolvedReference> _resolvedReferences;
|
||||||
|
private string _configuration;
|
||||||
|
|
||||||
|
public DotNetDependencyProvider(ProjectContext context, string configuration = Constants.DefaultConfiguration)
|
||||||
|
{
|
||||||
|
if (context == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(context));
|
||||||
|
}
|
||||||
|
|
||||||
|
_configuration = configuration;
|
||||||
|
_context = context;
|
||||||
|
DiscoverDependencies();
|
||||||
|
}
|
||||||
|
|
||||||
|
public IEnumerable<DependencyDescription> GetPackageDependencies()
|
||||||
|
{
|
||||||
|
return _packageDependencies;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IEnumerable<ResolvedReference> GetResolvedReferences()
|
||||||
|
{
|
||||||
|
return _resolvedReferences;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void DiscoverDependencies()
|
||||||
|
{
|
||||||
|
var exporter = _context.CreateExporter(_configuration);
|
||||||
|
|
||||||
|
if (exporter == null)
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException($"Couldn't create a library exporter for configuration {_configuration}");
|
||||||
|
}
|
||||||
|
|
||||||
|
var framework = _context.TargetFramework;
|
||||||
|
if (framework == null)
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException("Couldn't resolve dependencies when target framework is not specified.");
|
||||||
|
}
|
||||||
|
|
||||||
|
var exports = exporter.GetAllExports();
|
||||||
|
var nugetPackages = new Dictionary<string, DependencyDescription>(StringComparer.OrdinalIgnoreCase);
|
||||||
|
_resolvedReferences = new List<ResolvedReference>();
|
||||||
|
|
||||||
|
foreach (var export in exports)
|
||||||
|
{
|
||||||
|
var library = export.Library;
|
||||||
|
|
||||||
|
var description = new DependencyDescription(
|
||||||
|
library.Identity.Name,
|
||||||
|
library.Identity.Version.ToString(),
|
||||||
|
export.Library.Path,
|
||||||
|
framework.DotNetFrameworkName,
|
||||||
|
library.Identity.Type.Value,
|
||||||
|
library.Resolved);
|
||||||
|
|
||||||
|
foreach (var dependency in export.Library.Dependencies)
|
||||||
|
{
|
||||||
|
var dep = new Dependency(dependency.Name, version: string.Empty);
|
||||||
|
description.AddDependency(dep);
|
||||||
|
}
|
||||||
|
|
||||||
|
var itemSpec = $"{framework.DotNetFrameworkName}/{library.Identity.Name}/{library.Identity.Version.ToString()}";
|
||||||
|
nugetPackages[itemSpec] = description;
|
||||||
|
|
||||||
|
if (library.Resolved)
|
||||||
|
{
|
||||||
|
foreach (var asset in export.CompilationAssemblies)
|
||||||
|
{
|
||||||
|
var resolvedRef = new ResolvedReference(
|
||||||
|
name: Path.GetFileNameWithoutExtension(asset.FileName),
|
||||||
|
resolvedPath: asset.ResolvedPath);
|
||||||
|
_resolvedReferences.Add(resolvedRef);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_packageDependencies = nugetPackages.Values.ToList();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -5,6 +5,7 @@ using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using Microsoft.DotNet.ProjectModel;
|
using Microsoft.DotNet.ProjectModel;
|
||||||
|
using Microsoft.Extensions.ProjectModel.Resolution;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using Newtonsoft.Json.Linq;
|
using Newtonsoft.Json.Linq;
|
||||||
using NuGet.Frameworks;
|
using NuGet.Frameworks;
|
||||||
|
|
@ -17,6 +18,10 @@ namespace Microsoft.Extensions.ProjectModel
|
||||||
private readonly OutputPaths _paths;
|
private readonly OutputPaths _paths;
|
||||||
private readonly Lazy<JObject> _rawProject;
|
private readonly Lazy<JObject> _rawProject;
|
||||||
private readonly CommonCompilerOptions _compilerOptions;
|
private readonly CommonCompilerOptions _compilerOptions;
|
||||||
|
private readonly Lazy<DotNetDependencyProvider> _dependencyProvider;
|
||||||
|
|
||||||
|
private IEnumerable<DependencyDescription> _packageDependencies;
|
||||||
|
private IEnumerable<ResolvedReference> _compilationAssemblies;
|
||||||
|
|
||||||
public DotNetProjectContext(ProjectContext projectContext, string configuration, string outputPath)
|
public DotNetProjectContext(ProjectContext projectContext, string configuration, string outputPath)
|
||||||
{
|
{
|
||||||
|
|
@ -49,6 +54,8 @@ namespace Microsoft.Extensions.ProjectModel
|
||||||
// Workaround https://github.com/dotnet/cli/issues/3164
|
// Workaround https://github.com/dotnet/cli/issues/3164
|
||||||
IsClassLibrary = !(_compilerOptions.EmitEntryPoint
|
IsClassLibrary = !(_compilerOptions.EmitEntryPoint
|
||||||
?? projectContext.ProjectFile.GetCompilerOptions(null, configuration).EmitEntryPoint.GetValueOrDefault());
|
?? projectContext.ProjectFile.GetCompilerOptions(null, configuration).EmitEntryPoint.GetValueOrDefault());
|
||||||
|
|
||||||
|
_dependencyProvider = new Lazy<DotNetDependencyProvider>(() => new DotNetDependencyProvider(_projectContext));
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool IsClassLibrary { get; }
|
public bool IsClassLibrary { get; }
|
||||||
|
|
@ -79,6 +86,32 @@ namespace Microsoft.Extensions.ProjectModel
|
||||||
public IEnumerable<string> EmbededItems
|
public IEnumerable<string> EmbededItems
|
||||||
=> _compilerOptions.EmbedInclude.ResolveFiles();
|
=> _compilerOptions.EmbedInclude.ResolveFiles();
|
||||||
|
|
||||||
|
public IEnumerable<DependencyDescription> PackageDependencies
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (_packageDependencies == null)
|
||||||
|
{
|
||||||
|
_packageDependencies = _dependencyProvider.Value.GetPackageDependencies();
|
||||||
|
}
|
||||||
|
|
||||||
|
return _packageDependencies;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public IEnumerable<ResolvedReference> CompilationAssemblies
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (_compilationAssemblies == null)
|
||||||
|
{
|
||||||
|
_compilationAssemblies = _dependencyProvider.Value.GetResolvedReferences();
|
||||||
|
}
|
||||||
|
|
||||||
|
return _compilationAssemblies;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Returns string values of top-level keys in the project.json file
|
/// Returns string values of top-level keys in the project.json file
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@
|
||||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using Microsoft.Extensions.ProjectModel.Resolution;
|
||||||
using NuGet.Frameworks;
|
using NuGet.Frameworks;
|
||||||
|
|
||||||
namespace Microsoft.Extensions.ProjectModel
|
namespace Microsoft.Extensions.ProjectModel
|
||||||
|
|
@ -25,5 +26,7 @@ namespace Microsoft.Extensions.ProjectModel
|
||||||
IEnumerable<string> CompilationItems { get; }
|
IEnumerable<string> CompilationItems { get; }
|
||||||
IEnumerable<string> EmbededItems { get; }
|
IEnumerable<string> EmbededItems { get; }
|
||||||
string FindProperty(string propertyName);
|
string FindProperty(string propertyName);
|
||||||
|
IEnumerable<DependencyDescription> PackageDependencies { get;}
|
||||||
|
IEnumerable<ResolvedReference> CompilationAssemblies { get; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -7,6 +7,7 @@ using System.IO;
|
||||||
using Microsoft.Build.Execution;
|
using Microsoft.Build.Execution;
|
||||||
using NuGet.Frameworks;
|
using NuGet.Frameworks;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using Microsoft.Extensions.ProjectModel.Resolution;
|
||||||
|
|
||||||
namespace Microsoft.Extensions.ProjectModel
|
namespace Microsoft.Extensions.ProjectModel
|
||||||
{
|
{
|
||||||
|
|
@ -16,23 +17,28 @@ namespace Microsoft.Extensions.ProjectModel
|
||||||
private const string EmbedItemName = "EmbeddedResource";
|
private const string EmbedItemName = "EmbeddedResource";
|
||||||
private const string FullPathMetadataName = "FullPath";
|
private const string FullPathMetadataName = "FullPath";
|
||||||
|
|
||||||
private readonly ProjectInstance _project;
|
private readonly MsBuildProjectDependencyProvider _dependencyProvider;
|
||||||
private readonly string _name;
|
private IEnumerable<DependencyDescription> _packageDependencies;
|
||||||
|
private IEnumerable<ResolvedReference> _compilationAssemblies;
|
||||||
|
|
||||||
|
protected ProjectInstance Project { get; }
|
||||||
|
protected string Name { get; }
|
||||||
|
|
||||||
public MsBuildProjectContext(string name, string configuration, ProjectInstance project)
|
public MsBuildProjectContext(string name, string configuration, ProjectInstance project)
|
||||||
{
|
{
|
||||||
_project = project;
|
Project = project;
|
||||||
|
|
||||||
Configuration = configuration;
|
Configuration = configuration;
|
||||||
_name = name;
|
Name = name;
|
||||||
|
_dependencyProvider = new MsBuildProjectDependencyProvider(Project);
|
||||||
}
|
}
|
||||||
|
|
||||||
public string FindProperty(string propertyName)
|
public string FindProperty(string propertyName)
|
||||||
{
|
{
|
||||||
return _project.GetProperty(propertyName)?.EvaluatedValue;
|
return Project.GetProperty(propertyName)?.EvaluatedValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
public string ProjectName => FindProperty("ProjectName") ?? _name;
|
public string ProjectName => FindProperty("ProjectName") ?? Name;
|
||||||
public string Configuration { get; }
|
public string Configuration { get; }
|
||||||
|
|
||||||
public NuGetFramework TargetFramework
|
public NuGetFramework TargetFramework
|
||||||
|
|
@ -69,14 +75,41 @@ namespace Microsoft.Extensions.ProjectModel
|
||||||
}
|
}
|
||||||
public string AssemblyFullPath => FindProperty("TargetPath");
|
public string AssemblyFullPath => FindProperty("TargetPath");
|
||||||
public string Platform => FindProperty("Platform");
|
public string Platform => FindProperty("Platform");
|
||||||
public string ProjectFullPath => _project.FullPath;
|
public string ProjectFullPath => Project.FullPath;
|
||||||
public string RootNamespace => FindProperty("RootNamespace") ?? ProjectName;
|
public string RootNamespace => FindProperty("RootNamespace") ?? ProjectName;
|
||||||
public string TargetDirectory => FindProperty("TargetDir");
|
public string TargetDirectory => FindProperty("TargetDir");
|
||||||
|
|
||||||
public IEnumerable<string> CompilationItems
|
public IEnumerable<string> CompilationItems
|
||||||
=> _project.GetItems(CompileItemName).Select(i => i.GetMetadataValue(FullPathMetadataName));
|
=> Project.GetItems(CompileItemName).Select(i => i.GetMetadataValue(FullPathMetadataName));
|
||||||
|
|
||||||
public IEnumerable<string> EmbededItems
|
public IEnumerable<string> EmbededItems
|
||||||
=> _project.GetItems(EmbedItemName).Select(i => i.GetMetadataValue(FullPathMetadataName));
|
=> Project.GetItems(EmbedItemName).Select(i => i.GetMetadataValue(FullPathMetadataName));
|
||||||
|
|
||||||
|
public IEnumerable<DependencyDescription> PackageDependencies
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (_packageDependencies == null)
|
||||||
|
{
|
||||||
|
_packageDependencies = _dependencyProvider.GetPackageDependencies();
|
||||||
|
}
|
||||||
|
|
||||||
|
return _packageDependencies;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public IEnumerable<ResolvedReference> CompilationAssemblies
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (_compilationAssemblies == null)
|
||||||
|
{
|
||||||
|
_compilationAssemblies = _dependencyProvider.GetResolvedReferences();
|
||||||
|
}
|
||||||
|
|
||||||
|
return _compilationAssemblies;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -20,10 +20,10 @@ namespace Microsoft.Extensions.ProjectModel
|
||||||
{
|
{
|
||||||
internal class MsBuildProjectContextBuilder
|
internal class MsBuildProjectContextBuilder
|
||||||
{
|
{
|
||||||
private string _configuration;
|
protected string _configuration;
|
||||||
private IFileInfo _fileInfo;
|
protected IFileInfo _fileInfo;
|
||||||
private string[] _buildTargets;
|
protected string[] _buildTargets;
|
||||||
private Dictionary<string, string> _globalProperties = new Dictionary<string, string>();
|
protected Dictionary<string, string> _globalProperties = new Dictionary<string, string>();
|
||||||
private MsBuildContext _msbuildContext;
|
private MsBuildContext _msbuildContext;
|
||||||
|
|
||||||
public MsBuildProjectContextBuilder()
|
public MsBuildProjectContextBuilder()
|
||||||
|
|
@ -186,7 +186,7 @@ namespace Microsoft.Extensions.ProjectModel
|
||||||
|
|
||||||
protected virtual void Initialize()
|
protected virtual void Initialize()
|
||||||
{
|
{
|
||||||
WithBuildTargets(new[] { "ResolveReferences" });
|
WithBuildTargets(new[] { "ResolveReferences", "ResolvePackageDependenciesDesignTime" });
|
||||||
WithProperty("_ResolveReferenceDependencies", "true");
|
WithProperty("_ResolveReferenceDependencies", "true");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,126 @@
|
||||||
|
// Copyright (c) .NET Foundation. All rights reserved.
|
||||||
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using Microsoft.Build.Execution;
|
||||||
|
using Microsoft.Extensions.ProjectModel.Resolution;
|
||||||
|
|
||||||
|
namespace Microsoft.Extensions.ProjectModel
|
||||||
|
{
|
||||||
|
internal class MsBuildProjectDependencyProvider
|
||||||
|
{
|
||||||
|
private const string PackageDependencyItemType = "_DependenciesDesignTime";
|
||||||
|
private const string ResolvedReferenceItemType = "ReferencePath";
|
||||||
|
|
||||||
|
private readonly ProjectInstance _projectInstance;
|
||||||
|
public MsBuildProjectDependencyProvider(ProjectInstance projectInstance)
|
||||||
|
{
|
||||||
|
if (projectInstance == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(projectInstance));
|
||||||
|
}
|
||||||
|
_projectInstance = projectInstance;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IEnumerable<DependencyDescription> GetPackageDependencies()
|
||||||
|
{
|
||||||
|
var packageItems = _projectInstance.GetItems(PackageDependencyItemType);
|
||||||
|
var packageInfo = new Dictionary<string, DependencyDescription>(StringComparer.OrdinalIgnoreCase);
|
||||||
|
if (packageItems != null)
|
||||||
|
{
|
||||||
|
foreach (var packageItem in packageItems)
|
||||||
|
{
|
||||||
|
var packageDependency = CreateDependencyDescriptionFromItem(packageItem);
|
||||||
|
if (packageDependency != null)
|
||||||
|
{
|
||||||
|
packageInfo[packageItem.EvaluatedInclude] = packageDependency;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2nd pass to populate dependencies;
|
||||||
|
|
||||||
|
PopulateDependencies(packageInfo, packageItems);
|
||||||
|
}
|
||||||
|
|
||||||
|
return packageInfo.Values;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public IEnumerable<ResolvedReference> GetResolvedReferences()
|
||||||
|
{
|
||||||
|
var refItems = _projectInstance.GetItems(ResolvedReferenceItemType);
|
||||||
|
|
||||||
|
var resolvedReferences = refItems
|
||||||
|
?.Select(refItem => CreateResolvedReferenceFromProjectItem(refItem))
|
||||||
|
.Where(resolvedReference => resolvedReference != null);
|
||||||
|
|
||||||
|
return resolvedReferences;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static ResolvedReference CreateResolvedReferenceFromProjectItem(ProjectItemInstance item)
|
||||||
|
{
|
||||||
|
var resolvedPath = item.EvaluatedInclude;
|
||||||
|
|
||||||
|
if (string.IsNullOrEmpty(resolvedPath))
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
var name = Path.GetFileNameWithoutExtension(resolvedPath);
|
||||||
|
return new ResolvedReference(name, resolvedPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static DependencyDescription CreateDependencyDescriptionFromItem(ProjectItemInstance item)
|
||||||
|
{
|
||||||
|
// For type == Target, we do not get Name in the metadata. This is a special node where the dependencies are
|
||||||
|
// the direct dependencies of the project.
|
||||||
|
var itemSpec = item.EvaluatedInclude;
|
||||||
|
var name = item.HasMetadata("Name") ? item.GetMetadataValue("Name") : itemSpec;
|
||||||
|
|
||||||
|
if (string.IsNullOrEmpty(name))
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
var version = item.GetMetadataValue("Version");
|
||||||
|
var path = item.GetMetadataValue("Path");
|
||||||
|
var type = item.GetMetadataValue("Type");
|
||||||
|
var resolved = item.GetMetadataValue("Resolved");
|
||||||
|
|
||||||
|
bool isResolved;
|
||||||
|
isResolved = bool.TryParse(resolved, out isResolved) ? isResolved : false;
|
||||||
|
var framework = itemSpec.Split(new char[] { '/' }, StringSplitOptions.RemoveEmptyEntries).First();
|
||||||
|
|
||||||
|
return new DependencyDescription(name, version, path, framework, type, isResolved);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void PopulateDependencies(Dictionary<string, DependencyDescription> dependencies, ICollection<ProjectItemInstance> items)
|
||||||
|
{
|
||||||
|
foreach (var item in items)
|
||||||
|
{
|
||||||
|
var depSpecs = item.GetMetadataValue("Dependencies")
|
||||||
|
?.Split(new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries);
|
||||||
|
DependencyDescription currentDescription = null;
|
||||||
|
if (depSpecs == null || !dependencies.TryGetValue(item.EvaluatedInclude, out currentDescription))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var prefix = item.EvaluatedInclude.Split('/').FirstOrDefault();
|
||||||
|
foreach (var depSpec in depSpecs)
|
||||||
|
{
|
||||||
|
var spec = $"{prefix}/{depSpec}";
|
||||||
|
DependencyDescription dependency = null;
|
||||||
|
if (dependencies.TryGetValue(spec, out dependency))
|
||||||
|
{
|
||||||
|
var dep = new Dependency(dependency.Name, dependency.Version);
|
||||||
|
currentDescription.AddDependency(dep);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,26 @@
|
||||||
|
// Copyright (c) .NET Foundation. All rights reserved.
|
||||||
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Microsoft.Extensions.ProjectModel.Resolution
|
||||||
|
{
|
||||||
|
public class Dependency
|
||||||
|
{
|
||||||
|
public Dependency(string name, string version)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(name))
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(name));
|
||||||
|
}
|
||||||
|
|
||||||
|
Name = name;
|
||||||
|
Version = version;
|
||||||
|
}
|
||||||
|
public string Name { get; }
|
||||||
|
public string Version { get; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,51 @@
|
||||||
|
// Copyright (c) .NET Foundation. All rights reserved.
|
||||||
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Microsoft.Extensions.ProjectModel.Resolution
|
||||||
|
{
|
||||||
|
public class DependencyDescription
|
||||||
|
{
|
||||||
|
private readonly List<Dependency> _dependencies;
|
||||||
|
|
||||||
|
public DependencyDescription(string name, string version, string path, string framework, string type, bool isResolved)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(name))
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(name));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (string.IsNullOrEmpty(framework))
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(framework));
|
||||||
|
}
|
||||||
|
|
||||||
|
Name = name;
|
||||||
|
Version = version;
|
||||||
|
TargetFramework = framework;
|
||||||
|
Resolved = isResolved;
|
||||||
|
Path = path;
|
||||||
|
DependencyType dt;
|
||||||
|
Type = Enum.TryParse(type, ignoreCase: true , result: out dt) ? dt : DependencyType.Unknown;
|
||||||
|
|
||||||
|
_dependencies = new List<Dependency>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public string TargetFramework { get; }
|
||||||
|
public string Name { get; }
|
||||||
|
public string Path { get; }
|
||||||
|
public string Version { get; }
|
||||||
|
public DependencyType Type { get; }
|
||||||
|
public bool Resolved { get; }
|
||||||
|
public IEnumerable<Dependency> Dependencies => _dependencies;
|
||||||
|
|
||||||
|
public void AddDependency(Dependency dependency)
|
||||||
|
{
|
||||||
|
_dependencies.Add(dependency);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,20 @@
|
||||||
|
// Copyright (c) .NET Foundation. All rights reserved.
|
||||||
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Microsoft.Extensions.ProjectModel.Resolution
|
||||||
|
{
|
||||||
|
public enum DependencyType
|
||||||
|
{
|
||||||
|
Target,
|
||||||
|
Package,
|
||||||
|
Assembly,
|
||||||
|
Project,
|
||||||
|
AnalyzerAssembly,
|
||||||
|
Unknown
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,21 @@
|
||||||
|
// Copyright (c) .NET Foundation. All rights reserved.
|
||||||
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Microsoft.Extensions.ProjectModel.Resolution
|
||||||
|
{
|
||||||
|
public class ResolvedReference
|
||||||
|
{
|
||||||
|
public ResolvedReference(string name,string resolvedPath)
|
||||||
|
{
|
||||||
|
Name = name;
|
||||||
|
ResolvedPath = resolvedPath;
|
||||||
|
}
|
||||||
|
public string ResolvedPath { get; }
|
||||||
|
public string Name { get; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,88 @@
|
||||||
|
// Copyright (c) .NET Foundation. All rights reserved.
|
||||||
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using Microsoft.DotNet.Cli.Utils;
|
||||||
|
using Microsoft.DotNet.ProjectModel;
|
||||||
|
using Xunit;
|
||||||
|
using Xunit.Abstractions;
|
||||||
|
|
||||||
|
namespace Microsoft.Extensions.ProjectModel.DotNet
|
||||||
|
{
|
||||||
|
public class DotNetDependencyProviderTests
|
||||||
|
{
|
||||||
|
private const string projectJson = @"
|
||||||
|
{
|
||||||
|
""buildOptions"": {
|
||||||
|
},
|
||||||
|
""dependencies"": {
|
||||||
|
""Microsoft.AspNetCore.Mvc"": ""1.0.0-*"",
|
||||||
|
},
|
||||||
|
""frameworks"": {
|
||||||
|
""netcoreapp1.0"": {
|
||||||
|
""dependencies"": {
|
||||||
|
""Microsoft.NETCore.App"": {
|
||||||
|
""version"": ""1.0.0"",
|
||||||
|
""type"": ""platform""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
";
|
||||||
|
private readonly ITestOutputHelper _output;
|
||||||
|
|
||||||
|
public DotNetDependencyProviderTests(ITestOutputHelper output)
|
||||||
|
{
|
||||||
|
_output = output;
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void BuildProjectDependencies()
|
||||||
|
{
|
||||||
|
using (var fileProvider = new TemporaryFileProvider())
|
||||||
|
{
|
||||||
|
Directory.CreateDirectory(Path.Combine(fileProvider.Root, "demo"));
|
||||||
|
fileProvider.Add($"demo{Path.DirectorySeparatorChar}project.json", projectJson);
|
||||||
|
fileProvider.Add($"demo{Path.DirectorySeparatorChar}First.cs", "namespace demo { class First{} }");
|
||||||
|
|
||||||
|
var muxer = new Muxer().MuxerPath;
|
||||||
|
|
||||||
|
var result = Command
|
||||||
|
.Create(muxer, new[] { "restore", Path.Combine(fileProvider.Root, "demo") })
|
||||||
|
.OnErrorLine(l => _output.WriteLine(l))
|
||||||
|
.OnOutputLine(l => _output.WriteLine(l))
|
||||||
|
.Execute();
|
||||||
|
|
||||||
|
Assert.Equal(0, result.ExitCode);
|
||||||
|
var oldContext = ProjectContext
|
||||||
|
.CreateContextForEachFramework(Path.Combine(fileProvider.Root, "demo", "project.json"))
|
||||||
|
.First();
|
||||||
|
|
||||||
|
var context = new DotNetProjectContext(oldContext, "Debug", Path.Combine(fileProvider.Root, "demo", "bin"));
|
||||||
|
|
||||||
|
var home = Environment.GetEnvironmentVariable("USERPROFILE")
|
||||||
|
?? Environment.GetEnvironmentVariable("HOME");
|
||||||
|
var nugetPackageRoot = Path.Combine(home, ".nuget", "packages");
|
||||||
|
var expectedPackagePath = Path.Combine(nugetPackageRoot, "Microsoft.AspNetCore.Mvc", "1.0.0");
|
||||||
|
var expectedReferencePath = Path.Combine(expectedPackagePath, "lib", "netstandard1.6", "Microsoft.AspNetCore.Mvc.dll");
|
||||||
|
|
||||||
|
var assembly = context
|
||||||
|
.CompilationAssemblies
|
||||||
|
.Where(asm => asm.Name.Equals("Microsoft.AspNetCore.Mvc", StringComparison.OrdinalIgnoreCase))
|
||||||
|
.First();
|
||||||
|
|
||||||
|
Assert.Equal(expectedReferencePath, assembly.ResolvedPath);
|
||||||
|
|
||||||
|
var mvcPackage = context
|
||||||
|
.PackageDependencies
|
||||||
|
.Where(package => package.Name.Equals("Microsoft.AspNetCore.Mvc", StringComparison.OrdinalIgnoreCase))
|
||||||
|
.First();
|
||||||
|
|
||||||
|
Assert.Equal(expectedPackagePath, mvcPackage.Path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -102,6 +102,7 @@ namespace Microsoft.Extensions.ProjectModel
|
||||||
<Import Project=""$(MSBuildToolsPath)\Microsoft.CSharp.targets"" />
|
<Import Project=""$(MSBuildToolsPath)\Microsoft.CSharp.targets"" />
|
||||||
</Project>
|
</Project>
|
||||||
");
|
");
|
||||||
|
|
||||||
_files.Add("One.cs", "public class Abc {}");
|
_files.Add("One.cs", "public class Abc {}");
|
||||||
_files.Add("Two.cs", "public class Abc2 {}");
|
_files.Add("Two.cs", "public class Abc2 {}");
|
||||||
_files.Add("Excluded.cs", "public class Abc {}");
|
_files.Add("Excluded.cs", "public class Abc {}");
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,171 @@
|
||||||
|
// Copyright (c) .NET Foundation. All rights reserved.
|
||||||
|
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Linq;
|
||||||
|
using Microsoft.Extensions.ProjectModel.Tests;
|
||||||
|
using Xunit;
|
||||||
|
using Xunit.Abstractions;
|
||||||
|
using System.IO;
|
||||||
|
using Microsoft.DotNet.Cli.Utils;
|
||||||
|
using NuGet.Frameworks;
|
||||||
|
|
||||||
|
namespace Microsoft.Extensions.ProjectModel.MsBuild
|
||||||
|
{
|
||||||
|
public class MsBuildProjectDependencyProviderTests: IClassFixture<MsBuildFixture>
|
||||||
|
{
|
||||||
|
private const string NugetConfigTxt = @"
|
||||||
|
<configuration>
|
||||||
|
<packageSources>
|
||||||
|
<clear />
|
||||||
|
<add key=""NuGet"" value=""https://api.nuget.org/v3/index.json"" />
|
||||||
|
<add key=""dotnet-core"" value=""https://dotnet.myget.org/F/dotnet-core/api/v3/index.json"" />
|
||||||
|
<add key=""dotnet-buildtools"" value=""https://dotnet.myget.org/F/dotnet-buildtools/api/v3/index.json"" />
|
||||||
|
<add key=""nugetbuild"" value=""https://www.myget.org/F/nugetbuild/api/v3/index.json"" />
|
||||||
|
</packageSources>
|
||||||
|
</configuration>";
|
||||||
|
|
||||||
|
private const string RootProjectTxt = @"
|
||||||
|
<Project ToolsVersion=""14.0"" xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"">
|
||||||
|
<Import Project=""$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props"" />
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<RootNamespace>Microsoft.TestProject</RootNamespace>
|
||||||
|
<ProjectName>TestProject</ProjectName>
|
||||||
|
<OutputType>Library</OutputType>
|
||||||
|
<TargetFrameworks>netcoreapp1.0</TargetFrameworks>
|
||||||
|
<OutputPath>bin\$(Configuration)</OutputPath>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<Compile Include=""**\*.cs"" Exclude=""Excluded.cs"" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include=""Microsoft.AspNetCore.Mvc"">
|
||||||
|
<Version>1.0.0-*</Version>
|
||||||
|
</PackageReference>
|
||||||
|
<PackageReference Include=""Microsoft.NETCore.Sdk"">
|
||||||
|
<Version>1.0.0-*</Version>
|
||||||
|
</PackageReference>
|
||||||
|
<PackageReference Include=""Microsoft.NETCore.App"">
|
||||||
|
<Version>1.0.1</Version>
|
||||||
|
</PackageReference>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include=""..\Library1\library.csproj"" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Reference Include = ""xyz.dll"" />
|
||||||
|
</ItemGroup>
|
||||||
|
<Import Project=""$(MSBuildToolsPath)\Microsoft.CSharp.targets"" />
|
||||||
|
</Project>
|
||||||
|
";
|
||||||
|
|
||||||
|
private const string LibraryProjectTxt = @"
|
||||||
|
<Project ToolsVersion=""14.0"" xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"">
|
||||||
|
<Import Project=""$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props"" />
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<RootNamespace>Microsoft.Library</RootNamespace>
|
||||||
|
<ProjectName>Library1</ProjectName>
|
||||||
|
<OutputType>Library</OutputType>
|
||||||
|
<TargetFrameworks>netcoreapp1.0</TargetFrameworks>
|
||||||
|
<OutputPath>bin\$(Configuration)</OutputPath>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<Compile Include=""**\*.cs"" Exclude=""Excluded.cs"" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include=""Microsoft.NETCore.Sdk"">
|
||||||
|
<Version>1.0.0-*</Version>
|
||||||
|
</PackageReference>
|
||||||
|
<PackageReference Include=""Microsoft.NETCore.App"">
|
||||||
|
<Version>1.0.1</Version>
|
||||||
|
</PackageReference>
|
||||||
|
</ItemGroup>
|
||||||
|
<Import Project=""$(MSBuildToolsPath)\Microsoft.CSharp.targets"" />
|
||||||
|
</Project>
|
||||||
|
";
|
||||||
|
private readonly MsBuildFixture _fixture;
|
||||||
|
private readonly ITestOutputHelper _output;
|
||||||
|
|
||||||
|
public MsBuildProjectDependencyProviderTests(MsBuildFixture fixture, ITestOutputHelper output)
|
||||||
|
{
|
||||||
|
_fixture = fixture;
|
||||||
|
_output = output;
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact(Skip = "CI doesn't yet have a new enough version of .NET Core SDK")]
|
||||||
|
public void BuildDependenciesForProject()
|
||||||
|
{
|
||||||
|
using (var fileProvider = new TemporaryFileProvider())
|
||||||
|
{
|
||||||
|
Directory.CreateDirectory(Path.Combine(fileProvider.Root, "Root"));
|
||||||
|
Directory.CreateDirectory(Path.Combine(fileProvider.Root, "Library1"));
|
||||||
|
// TODO remove when SDK becomes available on other feeds
|
||||||
|
fileProvider.Add("NuGet.config", NugetConfigTxt);
|
||||||
|
|
||||||
|
// Add Root Project
|
||||||
|
fileProvider.Add($"Root{Path.DirectorySeparatorChar}test.csproj", RootProjectTxt);
|
||||||
|
fileProvider.Add($"Root{Path.DirectorySeparatorChar}One.cs", "public class Abc {}");
|
||||||
|
fileProvider.Add($"Root{Path.DirectorySeparatorChar}Two.cs", "public class Abc2 {}");
|
||||||
|
fileProvider.Add($"Root{Path.DirectorySeparatorChar}Excluded.cs", "public class Abc {}");
|
||||||
|
|
||||||
|
// Add Class Library project
|
||||||
|
fileProvider.Add($"Library1{Path.DirectorySeparatorChar}library.csproj", LibraryProjectTxt);
|
||||||
|
fileProvider.Add($"Library1{Path.DirectorySeparatorChar}Three.cs", "public class Abc3 {}");
|
||||||
|
|
||||||
|
var testContext = _fixture.GetMsBuildContext();
|
||||||
|
|
||||||
|
var muxer = Path.Combine(testContext.ExtensionsPath, "../..", "dotnet.exe");
|
||||||
|
var result = Command
|
||||||
|
.Create(muxer, new[] { "restore3", Path.Combine(fileProvider.Root, "Library1","Library1.csproj") })
|
||||||
|
.OnErrorLine(l => _output.WriteLine(l))
|
||||||
|
.OnOutputLine(l => _output.WriteLine(l))
|
||||||
|
.Execute();
|
||||||
|
|
||||||
|
Assert.Equal(0, result.ExitCode);
|
||||||
|
|
||||||
|
result = Command
|
||||||
|
.Create(muxer, new[] { "restore3", Path.Combine(fileProvider.Root, "Root", "test.csproj") })
|
||||||
|
.OnErrorLine(l => _output.WriteLine(l))
|
||||||
|
.OnOutputLine(l => _output.WriteLine(l))
|
||||||
|
.Execute();
|
||||||
|
|
||||||
|
Assert.Equal(0, result.ExitCode);
|
||||||
|
|
||||||
|
var builder = new MsBuildProjectContextBuilder()
|
||||||
|
.AsDesignTimeBuild()
|
||||||
|
.UseMsBuild(testContext)
|
||||||
|
.WithTargetFramework(FrameworkConstants.CommonFrameworks.NetCoreApp10)
|
||||||
|
.WithConfiguration("Debug")
|
||||||
|
.WithProjectFile(fileProvider.GetFileInfo(Path.Combine("Root", "test.csproj")));
|
||||||
|
|
||||||
|
var context = builder.Build();
|
||||||
|
|
||||||
|
var compilationAssemblies = context.CompilationAssemblies;
|
||||||
|
var lib1Dll = compilationAssemblies
|
||||||
|
.Where(assembly => assembly.Name.Equals("Library1", StringComparison.OrdinalIgnoreCase))
|
||||||
|
.FirstOrDefault();
|
||||||
|
|
||||||
|
Assert.NotNull(lib1Dll);
|
||||||
|
var expectedPath = Path.Combine(fileProvider.Root, "Root", "bin", "Debug", "netcoreapp1.0", "lib1.dll");
|
||||||
|
Assert.Equal(expectedPath, lib1Dll.ResolvedPath, ignoreCase: true);
|
||||||
|
|
||||||
|
// This reference doesn't resolve so should not be available here.
|
||||||
|
Assert.False(compilationAssemblies.Any(assembly => assembly.Name.Equals("xyz", StringComparison.OrdinalIgnoreCase)));
|
||||||
|
|
||||||
|
var packageDependencies = context.PackageDependencies;
|
||||||
|
var mvcPackage = packageDependencies
|
||||||
|
.Where(p => p.Name.Equals("Microsoft.AspNetCore.Mvc", StringComparison.OrdinalIgnoreCase))
|
||||||
|
.FirstOrDefault();
|
||||||
|
Assert.NotNull(mvcPackage);
|
||||||
|
|
||||||
|
Assert.True(mvcPackage.Dependencies.Any(dependency => dependency.Name.Equals("Microsoft.Extensions.DependencyInjection", StringComparison.OrdinalIgnoreCase)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue