Merge pull request #4517 from livarcocc/promote_project_dependencies

Promote project dependencies
This commit is contained in:
Livar 2016-10-28 15:17:47 -07:00 committed by GitHub
commit cbed94dbef
9 changed files with 144 additions and 47 deletions

View file

@ -3,8 +3,7 @@
<PropertyGroup> <PropertyGroup>
<OutputType>Library</OutputType> <OutputType>Library</OutputType>
<TargetFrameworkIdentifier>.NETStandard</TargetFrameworkIdentifier> <TargetFramework>netstandard1.5</TargetFramework>
<TargetFrameworkVersion>v1.5</TargetFrameworkVersion>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
@ -13,5 +12,15 @@
<None Include="project.json" /> <None Include="project.json" />
</ItemGroup> </ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.NET.Sdk">
<Version>1.0.0-alpha-20161026-2</Version>
<PrivateAssets>All</PrivateAssets>
</PackageReference>
<PackageReference Include="NETStandard.Library">
<Version>1.6.0</Version>
</PackageReference>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project> </Project>

View file

@ -3,8 +3,7 @@
<PropertyGroup> <PropertyGroup>
<OutputType>Library</OutputType> <OutputType>Library</OutputType>
<TargetFrameworkIdentifier>.NETStandard</TargetFrameworkIdentifier> <TargetFramework>netstandard1.5</TargetFramework>
<TargetFrameworkVersion>v1.5</TargetFrameworkVersion>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
@ -13,5 +12,15 @@
<None Include="project.json" /> <None Include="project.json" />
</ItemGroup> </ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.NET.Sdk">
<Version>1.0.0-alpha-20161026-2</Version>
<PrivateAssets>All</PrivateAssets>
</PackageReference>
<PackageReference Include="NETStandard.Library">
<Version>1.6.0</Version>
</PackageReference>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project> </Project>

View file

@ -3,8 +3,7 @@
<PropertyGroup> <PropertyGroup>
<OutputType>Library</OutputType> <OutputType>Library</OutputType>
<TargetFrameworkIdentifier>.NETStandard</TargetFrameworkIdentifier> <TargetFramework>netstandard1.5</TargetFramework>
<TargetFrameworkVersion>v1.5</TargetFrameworkVersion>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
@ -13,5 +12,15 @@
<None Include="project.json" /> <None Include="project.json" />
</ItemGroup> </ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.NET.Sdk">
<Version>1.0.0-alpha-20161026-2</Version>
<PrivateAssets>All</PrivateAssets>
</PackageReference>
<PackageReference Include="NETStandard.Library">
<Version>1.6.0</Version>
</PackageReference>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project> </Project>

View file

@ -3,6 +3,7 @@
using System; using System;
using System.Diagnostics; using System.Diagnostics;
using TestLibrary;
namespace TestApp namespace TestApp
{ {
@ -11,6 +12,7 @@ namespace TestApp
public static int Main(string[] args) public static int Main(string[] args)
{ {
Console.WriteLine("This string came from ProjectA"); Console.WriteLine("This string came from ProjectA");
Console.WriteLine($"{ProjectD.GetMessage()}");
return 0; return 0;
} }
} }

View file

@ -17,6 +17,19 @@ namespace Microsoft.DotNet.ProjectJsonMigration
{ {
internal class ProjectDependencyFinder internal class ProjectDependencyFinder
{ {
public IEnumerable<ProjectDependency> ResolveProjectDependencies(
IEnumerable<ProjectContext> projectContexts,
IEnumerable<string> preResolvedProjects = null)
{
foreach (var projectContext in projectContexts)
{
foreach (var projectDependency in ResolveProjectDependencies(projectContext, preResolvedProjects))
{
yield return projectDependency;
}
}
}
public IEnumerable<ProjectDependency> ResolveProjectDependencies(string projectDir, string xprojFile = null) public IEnumerable<ProjectDependency> ResolveProjectDependencies(string projectDir, string xprojFile = null)
{ {
var projectContexts = ProjectContext.CreateContextForEachFramework(projectDir); var projectContexts = ProjectContext.CreateContextForEachFramework(projectDir);
@ -31,20 +44,37 @@ namespace Microsoft.DotNet.ProjectJsonMigration
return ResolveProjectDependencies(projectContexts, ResolveXProjProjectDependencyNames(xproj)); return ResolveProjectDependencies(projectContexts, ResolveXProjProjectDependencyNames(xproj));
} }
public IEnumerable<ProjectDependency> ResolveProjectDependencies( public IEnumerable<ProjectDependency> ResolveAllProjectDependenciesForFramework(
IEnumerable<ProjectContext> projectContexts, ProjectDependency projectToResolve,
IEnumerable<string> preResolvedProjects = null) NuGetFramework framework,
IEnumerable<string> preResolvedProjects=null)
{ {
foreach (var projectContext in projectContexts) var projects = new List<ProjectDependency> { projectToResolve };
var allDependencies = new List<ProjectDependency>();
while (projects.Count > 0)
{ {
foreach (var projectDependency in ResolveProjectDependencies(projectContext, preResolvedProjects)) var project = projects.First();
projects.Remove(project);
var projectContext =
ProjectContext.CreateContextForEachFramework(project.ProjectFilePath).FirstOrDefault();
if(projectContext == null)
{ {
yield return projectDependency; continue;
} }
var dependencies = ResolveDirectProjectDependenciesForFramework(
projectContext.ProjectFile,
framework,
preResolvedProjects
);
projects.AddRange(dependencies);
allDependencies.AddRange(dependencies);
} }
return allDependencies;
} }
public IEnumerable<ProjectDependency> ResolveProjectDependenciesForFramework( public IEnumerable<ProjectDependency> ResolveDirectProjectDependenciesForFramework(
Project project, Project project,
NuGetFramework framework, NuGetFramework framework,
IEnumerable<string> preResolvedProjects=null) IEnumerable<string> preResolvedProjects=null)
@ -98,7 +128,37 @@ namespace Microsoft.DotNet.ProjectJsonMigration
return projectDependencies; return projectDependencies;
} }
public IEnumerable<ProjectDependency> ResolveProjectDependencies(ProjectContext projectContext, IEnumerable<string> preResolvedProjects=null) internal IEnumerable<ProjectItemElement> ResolveXProjProjectDependencies(ProjectRootElement xproj)
{
if (xproj == null)
{
MigrationTrace.Instance.WriteLine($"{nameof(ProjectDependencyFinder)}: No xproj file given.");
return Enumerable.Empty<ProjectItemElement>();
}
return xproj.Items
.Where(i => i.ItemType == "ProjectReference")
.Where(p => p.Includes().Any(
include => string.Equals(Path.GetExtension(include), ".csproj", StringComparison.OrdinalIgnoreCase)));
}
internal string FindXprojFile(string projectDirectory)
{
var allXprojFiles = Directory.EnumerateFiles(projectDirectory, "*.xproj", SearchOption.TopDirectoryOnly);
if (allXprojFiles.Count() > 1)
{
MigrationErrorCodes
.MIGRATE1017($"Multiple xproj files found in {projectDirectory}, please specify which to use")
.Throw();
}
return allXprojFiles.FirstOrDefault();
}
private IEnumerable<ProjectDependency> ResolveProjectDependencies(
ProjectContext projectContext,
IEnumerable<string> preResolvedProjects=null)
{ {
preResolvedProjects = preResolvedProjects ?? new HashSet<string>(); preResolvedProjects = preResolvedProjects ?? new HashSet<string>();
@ -144,34 +204,6 @@ namespace Microsoft.DotNet.ProjectJsonMigration
PathUtility.GetPathWithDirectorySeparator(p)))); PathUtility.GetPathWithDirectorySeparator(p))));
} }
internal IEnumerable<ProjectItemElement> ResolveXProjProjectDependencies(ProjectRootElement xproj)
{
if (xproj == null)
{
MigrationTrace.Instance.WriteLine($"{nameof(ProjectDependencyFinder)}: No xproj file given.");
return Enumerable.Empty<ProjectItemElement>();
}
return xproj.Items
.Where(i => i.ItemType == "ProjectReference")
.Where(p => p.Includes().Any(
include => string.Equals(Path.GetExtension(include), ".csproj", StringComparison.OrdinalIgnoreCase)));
}
internal string FindXprojFile(string projectDirectory)
{
var allXprojFiles = Directory.EnumerateFiles(projectDirectory, "*.xproj", SearchOption.TopDirectoryOnly);
if (allXprojFiles.Count() > 1)
{
MigrationErrorCodes
.MIGRATE1017($"Multiple xproj files found in {projectDirectory}, please specify which to use")
.Throw();
}
return allXprojFiles.FirstOrDefault();
}
private Dictionary<string, ProjectDependency> FindPossibleProjectDependencies(string projectJsonFilePath) private Dictionary<string, ProjectDependency> FindPossibleProjectDependencies(string projectJsonFilePath)
{ {
var projectRootDirectory = GetRootFromProjectJson(projectJsonFilePath); var projectRootDirectory = GetRootFromProjectJson(projectJsonFilePath);

View file

@ -244,7 +244,7 @@ namespace Microsoft.DotNet.ProjectJsonMigration.Rules
var migratedXProjDependencyPaths = csprojReferenceItems.SelectMany(p => p.Includes()); var migratedXProjDependencyPaths = csprojReferenceItems.SelectMany(p => p.Includes());
var migratedXProjDependencyNames = new HashSet<string>(migratedXProjDependencyPaths.Select(p => Path.GetFileNameWithoutExtension( var migratedXProjDependencyNames = new HashSet<string>(migratedXProjDependencyPaths.Select(p => Path.GetFileNameWithoutExtension(
PathUtility.GetPathWithDirectorySeparator(p)))); PathUtility.GetPathWithDirectorySeparator(p))));
var projectDependencies = _projectDependencyFinder.ResolveProjectDependenciesForFramework( var projectDependencies = _projectDependencyFinder.ResolveDirectProjectDependenciesForFramework(
project, project,
framework, framework,
preResolvedProjects: migratedXProjDependencyNames); preResolvedProjects: migratedXProjDependencyNames);

View file

@ -30,8 +30,9 @@ namespace Microsoft.DotNet.ProjectJsonMigration.Rules
_projectDirectory = migrationSettings.ProjectDirectory; _projectDirectory = migrationSettings.ProjectDirectory;
var migratedXProjDependencyPaths = MigrateXProjProjectDependencies(migrationRuleInputs); var migratedXProjDependencyPaths = MigrateXProjProjectDependencies(migrationRuleInputs);
var migratedXProjDependencyNames = new HashSet<string>(migratedXProjDependencyPaths.Select(p => Path.GetFileNameWithoutExtension( var migratedXProjDependencyNames = new HashSet<string>(
PathUtility.GetPathWithDirectorySeparator(p)))); migratedXProjDependencyPaths.Select(p =>
Path.GetFileNameWithoutExtension(PathUtility.GetPathWithDirectorySeparator(p))));
MigrateProjectJsonProjectDependencies( MigrateProjectJsonProjectDependencies(
migrationRuleInputs.ProjectContexts, migrationRuleInputs.ProjectContexts,
migratedXProjDependencyNames, migratedXProjDependencyNames,
@ -104,8 +105,8 @@ namespace Microsoft.DotNet.ProjectJsonMigration.Rules
HashSet<string> migratedXProjDependencyNames, HashSet<string> migratedXProjDependencyNames,
ProjectRootElement outputMSBuildProject) ProjectRootElement outputMSBuildProject)
{ {
var projectDependencies = _projectDependencyFinder.ResolveProjectDependenciesForFramework( var projectDependencies = _projectDependencyFinder.ResolveAllProjectDependenciesForFramework(
project, new ProjectDependency(project.Name, project.ProjectFilePath),
framework, framework,
migratedXProjDependencyNames); migratedXProjDependencyNames);

View file

@ -238,5 +238,25 @@ namespace Microsoft.DotNet.ProjectJsonMigration.Tests
migratedProjectReferenceItem.Include.Should().Be(projectReference); migratedProjectReferenceItem.Include.Should().Be(projectReference);
migratedProjectReferenceItem.Condition.Should().Be(" '$(Bar)' == 'foo' and '$(Foo)' == 'bar' "); migratedProjectReferenceItem.Condition.Should().Be(" '$(Bar)' == 'foo' and '$(Foo)' == 'bar' ");
} }
[Fact]
public void It_promotes_P2P_references_up_in_the_dependency_chain()
{
var solutionDirectory =
TestAssetsManager.CreateTestInstance("TestAppDependencyGraph", callingMethod: "p").Path;
var appDirectory = Path.Combine(solutionDirectory, "ProjectA");
var projectContext = ProjectContext.Create(appDirectory, FrameworkConstants.CommonFrameworks.NetCoreApp10);
var mockProj = ProjectRootElement.Create();
var testSettings = new MigrationSettings(appDirectory, appDirectory, "1.0.0", mockProj, null);
var testInputs = new MigrationRuleInputs(new[] {projectContext}, mockProj, mockProj.AddItemGroup(),
mockProj.AddPropertyGroup());
new MigrateProjectDependenciesRule().Apply(testSettings, testInputs);
var projectReferences = mockProj.Items.Where(
item => item.ItemType.Equals("ProjectReference", StringComparison.Ordinal));
projectReferences.Count().Should().Be(7);
}
} }
} }

View file

@ -375,6 +375,21 @@ namespace Microsoft.DotNet.Migration.Tests
VerifyAllMSBuildOutputsRunnable(projectDirectory); VerifyAllMSBuildOutputsRunnable(projectDirectory);
} }
[Fact]
public void It_builds_a_migrated_app_with_a_indirect_dependency()
{
const string projectName = "ProjectA";
var solutionDirectory =
TestAssetsManager.CreateTestInstance("TestAppDependencyGraph", callingMethod: "p").Path;
var projectDirectory = Path.Combine(solutionDirectory, projectName);
MigrateProject(new string[] { projectDirectory });
Restore(projectDirectory);
BuildMSBuild(projectDirectory, projectName);
VerifyAllMSBuildOutputsRunnable(projectDirectory);
}
private void VerifyAutoInjectedDesktopReferences(string projectDirectory, string projectName, bool shouldBePresent) private void VerifyAutoInjectedDesktopReferences(string projectDirectory, string projectName, bool shouldBePresent)
{ {
if (projectName != null) if (projectName != null)