Marking hoisted P2P projects with a FromP2P attribute. (#4598)
This commit is contained in:
parent
016a88b52a
commit
de5da5870f
4 changed files with 103 additions and 23 deletions
|
@ -7,11 +7,25 @@ namespace Microsoft.DotNet.ProjectJsonMigration
|
||||||
{
|
{
|
||||||
public string Name { get; }
|
public string Name { get; }
|
||||||
public string ProjectFilePath { get; }
|
public string ProjectFilePath { get; }
|
||||||
|
public bool Hoisted { get; }
|
||||||
|
|
||||||
public ProjectDependency(string name, string projectFilePath)
|
public ProjectDependency(string name, string projectFilePath, bool hoisted)
|
||||||
{
|
{
|
||||||
Name = name;
|
Name = name;
|
||||||
ProjectFilePath = System.IO.Path.GetFullPath(projectFilePath);
|
ProjectFilePath = System.IO.Path.GetFullPath(projectFilePath);
|
||||||
|
Hoisted = hoisted;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool Equals(object obj)
|
||||||
|
{
|
||||||
|
var other = obj as ProjectDependency;
|
||||||
|
|
||||||
|
return other != null && other.ProjectFilePath == ProjectFilePath;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override int GetHashCode()
|
||||||
|
{
|
||||||
|
return ProjectFilePath.GetHashCode();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -50,7 +50,7 @@ namespace Microsoft.DotNet.ProjectJsonMigration
|
||||||
IEnumerable<string> preResolvedProjects=null)
|
IEnumerable<string> preResolvedProjects=null)
|
||||||
{
|
{
|
||||||
var projects = new List<ProjectDependency> { projectToResolve };
|
var projects = new List<ProjectDependency> { projectToResolve };
|
||||||
var allDependencies = new List<ProjectDependency>();
|
var allDependencies = new HashSet<ProjectDependency>();
|
||||||
while (projects.Count > 0)
|
while (projects.Count > 0)
|
||||||
{
|
{
|
||||||
var project = projects.First();
|
var project = projects.First();
|
||||||
|
@ -65,24 +65,33 @@ namespace Microsoft.DotNet.ProjectJsonMigration
|
||||||
var dependencies = ResolveDirectProjectDependenciesForFramework(
|
var dependencies = ResolveDirectProjectDependenciesForFramework(
|
||||||
projectContext.ProjectFile,
|
projectContext.ProjectFile,
|
||||||
framework,
|
framework,
|
||||||
preResolvedProjects
|
preResolvedProjects,
|
||||||
|
HoistDependenciesThatAreNotDirectDependencies(projectToResolve, project)
|
||||||
);
|
);
|
||||||
projects.AddRange(dependencies);
|
projects.AddRange(dependencies);
|
||||||
allDependencies.AddRange(dependencies);
|
allDependencies.UnionWith(dependencies);
|
||||||
}
|
}
|
||||||
|
|
||||||
return allDependencies;
|
return allDependencies;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private bool HoistDependenciesThatAreNotDirectDependencies(
|
||||||
|
ProjectDependency originalProject,
|
||||||
|
ProjectDependency dependenciesOwner)
|
||||||
|
{
|
||||||
|
return originalProject != dependenciesOwner;
|
||||||
|
}
|
||||||
|
|
||||||
public IEnumerable<ProjectDependency> ResolveDirectProjectDependenciesForFramework(
|
public IEnumerable<ProjectDependency> ResolveDirectProjectDependenciesForFramework(
|
||||||
Project project,
|
Project project,
|
||||||
NuGetFramework framework,
|
NuGetFramework framework,
|
||||||
IEnumerable<string> preResolvedProjects=null)
|
IEnumerable<string> preResolvedProjects=null,
|
||||||
|
bool hoistedDependencies = false)
|
||||||
{
|
{
|
||||||
preResolvedProjects = preResolvedProjects ?? new HashSet<string>();
|
preResolvedProjects = preResolvedProjects ?? new HashSet<string>();
|
||||||
|
|
||||||
var possibleProjectDependencies =
|
var possibleProjectDependencies =
|
||||||
FindPossibleProjectDependencies(project.ProjectFilePath);
|
FindPossibleProjectDependencies(project.ProjectFilePath, hoistedDependencies);
|
||||||
|
|
||||||
var projectDependencies = new List<ProjectDependency>();
|
var projectDependencies = new List<ProjectDependency>();
|
||||||
|
|
||||||
|
@ -205,7 +214,9 @@ namespace Microsoft.DotNet.ProjectJsonMigration
|
||||||
PathUtility.GetPathWithDirectorySeparator(p))));
|
PathUtility.GetPathWithDirectorySeparator(p))));
|
||||||
}
|
}
|
||||||
|
|
||||||
private Dictionary<string, ProjectDependency> FindPossibleProjectDependencies(string projectJsonFilePath)
|
private Dictionary<string, ProjectDependency> FindPossibleProjectDependencies(
|
||||||
|
string projectJsonFilePath,
|
||||||
|
bool hoistedDependencies = false)
|
||||||
{
|
{
|
||||||
var projectRootDirectory = GetRootFromProjectJson(projectJsonFilePath);
|
var projectRootDirectory = GetRootFromProjectJson(projectJsonFilePath);
|
||||||
|
|
||||||
|
@ -217,7 +228,7 @@ namespace Microsoft.DotNet.ProjectJsonMigration
|
||||||
|
|
||||||
var projects = new Dictionary<string, ProjectDependency>(StringComparer.Ordinal);
|
var projects = new Dictionary<string, ProjectDependency>(StringComparer.Ordinal);
|
||||||
|
|
||||||
foreach (var project in GetPotentialProjects(projectSearchPaths))
|
foreach (var project in GetPotentialProjects(projectSearchPaths, hoistedDependencies))
|
||||||
{
|
{
|
||||||
if (projects.ContainsKey(project.Name))
|
if (projects.ContainsKey(project.Name))
|
||||||
{
|
{
|
||||||
|
@ -278,7 +289,9 @@ namespace Microsoft.DotNet.ProjectJsonMigration
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Create the list of potential projects from the search paths.
|
/// Create the list of potential projects from the search paths.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private static List<ProjectDependency> GetPotentialProjects(IEnumerable<string> searchPaths)
|
private static List<ProjectDependency> GetPotentialProjects(
|
||||||
|
IEnumerable<string> searchPaths,
|
||||||
|
bool hoistedDependencies = false)
|
||||||
{
|
{
|
||||||
var projects = new List<ProjectDependency>();
|
var projects = new List<ProjectDependency>();
|
||||||
|
|
||||||
|
@ -301,7 +314,10 @@ namespace Microsoft.DotNet.ProjectJsonMigration
|
||||||
// Instead, we'll do an exists check when we try to resolve
|
// Instead, we'll do an exists check when we try to resolve
|
||||||
|
|
||||||
// Check if we've already added this, just in case it was pre-loaded into the cache
|
// Check if we've already added this, just in case it was pre-loaded into the cache
|
||||||
var project = new ProjectDependency(projectDirectory.Name, projectFilePath);
|
var project = new ProjectDependency(
|
||||||
|
projectDirectory.Name,
|
||||||
|
projectFilePath,
|
||||||
|
hoistedDependencies);
|
||||||
|
|
||||||
projects.Add(project);
|
projects.Add(project);
|
||||||
}
|
}
|
||||||
|
|
|
@ -106,12 +106,15 @@ namespace Microsoft.DotNet.ProjectJsonMigration.Rules
|
||||||
ProjectRootElement outputMSBuildProject)
|
ProjectRootElement outputMSBuildProject)
|
||||||
{
|
{
|
||||||
var projectDependencies = _projectDependencyFinder.ResolveAllProjectDependenciesForFramework(
|
var projectDependencies = _projectDependencyFinder.ResolveAllProjectDependenciesForFramework(
|
||||||
new ProjectDependency(project.Name, project.ProjectFilePath),
|
new ProjectDependency(project.Name, project.ProjectFilePath, false),
|
||||||
framework,
|
framework,
|
||||||
migratedXProjDependencyNames);
|
migratedXProjDependencyNames);
|
||||||
|
|
||||||
var projectDependencyTransformResults =
|
var projectDependencyTransformResults =
|
||||||
projectDependencies.Select(p => ProjectDependencyTransform.Transform(p));
|
projectDependencies.Select(p =>
|
||||||
|
p.Hoisted ?
|
||||||
|
HoistedDependencyTransform.Transform(p) :
|
||||||
|
ProjectDependencyTransform.Transform(p));
|
||||||
|
|
||||||
if (projectDependencyTransformResults.Any())
|
if (projectDependencyTransformResults.Any())
|
||||||
{
|
{
|
||||||
|
@ -138,18 +141,26 @@ namespace Microsoft.DotNet.ProjectJsonMigration.Rules
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private AddItemTransform<ProjectDependency> ProjectDependencyTransform => new AddItemTransform<ProjectDependency>(
|
private AddItemTransform<ProjectDependency> ProjectDependencyTransform =>
|
||||||
"ProjectReference",
|
GetProjectDependencyTransfrom();
|
||||||
dep =>
|
|
||||||
{
|
|
||||||
var projectDir = Path.GetDirectoryName(dep.ProjectFilePath);
|
|
||||||
var migratedProjectFileName = Path.GetFileName(projectDir) + ".csproj";
|
|
||||||
var relativeProjectDir = PathUtility.GetRelativePath(_projectDirectory + "/", projectDir);
|
|
||||||
|
|
||||||
return Path.Combine(relativeProjectDir, migratedProjectFileName);
|
private AddItemTransform<ProjectDependency> HoistedDependencyTransform =>
|
||||||
},
|
GetProjectDependencyTransfrom()
|
||||||
dep => "",
|
.WithMetadata("FromP2P", "true");
|
||||||
dep => true);
|
|
||||||
|
private Func<AddItemTransform<ProjectDependency>> GetProjectDependencyTransfrom =>
|
||||||
|
() => new AddItemTransform<ProjectDependency>(
|
||||||
|
"ProjectReference",
|
||||||
|
dep =>
|
||||||
|
{
|
||||||
|
var projectDir = Path.GetDirectoryName(dep.ProjectFilePath);
|
||||||
|
var migratedProjectFileName = Path.GetFileName(projectDir) + ".csproj";
|
||||||
|
var relativeProjectDir = PathUtility.GetRelativePath(_projectDirectory + "/", projectDir);
|
||||||
|
|
||||||
|
return Path.Combine(relativeProjectDir, migratedProjectFileName);
|
||||||
|
},
|
||||||
|
dep => "",
|
||||||
|
dep => true);
|
||||||
|
|
||||||
private AddItemTransform<string> ProjectDependencyStringTransform => new AddItemTransform<string>(
|
private AddItemTransform<string> ProjectDependencyStringTransform => new AddItemTransform<string>(
|
||||||
"ProjectReference",
|
"ProjectReference",
|
||||||
|
|
|
@ -249,6 +249,45 @@ namespace Microsoft.DotNet.ProjectJsonMigration.Tests
|
||||||
projectReferences.Count().Should().Be(7);
|
projectReferences.Count().Should().Be(7);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void All_promoted_P2P_references_are_marked_with_a_FromP2P_attribute()
|
||||||
|
{
|
||||||
|
var expectedHoistedProjectReferences = new [] {
|
||||||
|
Path.Combine("..", "ProjectD", "ProjectD.csproj"),
|
||||||
|
Path.Combine("..", "ProjectE", "ProjectE.csproj"),
|
||||||
|
Path.Combine("..", "CsprojLibrary1", "CsprojLibrary1.csproj"),
|
||||||
|
Path.Combine("..", "CsprojLibrary2", "CsprojLibrary2.csproj"),
|
||||||
|
Path.Combine("..", "CsprojLibrary3", "CsprojLibrary3.csproj")
|
||||||
|
};
|
||||||
|
|
||||||
|
var mockProj = MigrateProject("TestAppDependencyGraph", "ProjectA");
|
||||||
|
|
||||||
|
var projectReferences = mockProj.Items
|
||||||
|
.Where(item =>
|
||||||
|
item.ItemType == "ProjectReference" && item.GetMetadataWithName("FromP2P") != null)
|
||||||
|
.Select(i => i.Include);
|
||||||
|
|
||||||
|
projectReferences.Should().BeEquivalentTo(expectedHoistedProjectReferences);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void All_non_promoted_P2P_references_are_not_marked_with_a_FromP2P_attribute()
|
||||||
|
{
|
||||||
|
var expectedNonHoistedProjectReferences = new [] {
|
||||||
|
Path.Combine("..", "ProjectB", "ProjectB.csproj"),
|
||||||
|
Path.Combine("..", "ProjectC", "ProjectC.csproj")
|
||||||
|
};
|
||||||
|
|
||||||
|
var mockProj = MigrateProject("TestAppDependencyGraph", "ProjectA");
|
||||||
|
|
||||||
|
var projectReferences = mockProj.Items
|
||||||
|
.Where(item =>
|
||||||
|
item.ItemType == "ProjectReference" && item.GetMetadataWithName("FromP2P") == null)
|
||||||
|
.Select(i => i.Include);
|
||||||
|
|
||||||
|
projectReferences.Should().BeEquivalentTo(expectedNonHoistedProjectReferences);
|
||||||
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void It_migrates_unqualified_dependencies_as_ProjectReference_when_a_matching_project_is_found()
|
public void It_migrates_unqualified_dependencies_as_ProjectReference_when_a_matching_project_is_found()
|
||||||
{
|
{
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue