dotnet-installer/src/Microsoft.DotNet.ProjectJsonMigration/Rules/MigratePackageDependenciesAndToolsRule.cs

255 lines
11 KiB
C#
Raw Normal View History

2016-09-26 21:40:11 -07: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.
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Microsoft.Build.Construction;
2016-10-03 20:10:09 -07:00
using Microsoft.DotNet.Cli.Utils;
2016-09-26 21:40:11 -07:00
using Microsoft.DotNet.ProjectJsonMigration.Transforms;
using Microsoft.DotNet.ProjectModel;
using Microsoft.DotNet.ProjectModel.Graph;
using Microsoft.DotNet.Tools.Common;
using NuGet.Frameworks;
using NuGet.LibraryModel;
namespace Microsoft.DotNet.ProjectJsonMigration.Rules
{
2016-10-05 11:36:23 -07:00
public class MigratePackageDependenciesAndToolsRule : IMigrationRule
2016-09-26 21:40:11 -07:00
{
private readonly ITransformApplicator _transformApplicator;
private readonly ProjectDependencyFinder _projectDependencyFinder;
private string _projectDirectory;
2016-10-05 11:36:23 -07:00
public MigratePackageDependenciesAndToolsRule(ITransformApplicator transformApplicator = null)
2016-09-26 21:40:11 -07:00
{
_transformApplicator = transformApplicator ?? new TransformApplicator();
_projectDependencyFinder = new ProjectDependencyFinder();
}
public void Apply(MigrationSettings migrationSettings, MigrationRuleInputs migrationRuleInputs)
{
CleanExistingPackageReferences(migrationRuleInputs.OutputMSBuildProject);
_projectDirectory = migrationSettings.ProjectDirectory;
var project = migrationRuleInputs.DefaultProjectContext.ProjectFile;
var tfmDependencyMap = new Dictionary<string, IEnumerable<ProjectLibraryDependency>>();
var targetFrameworks = project.GetTargetFrameworks();
// Inject Sdk dependency
2016-10-03 20:10:09 -07:00
_transformApplicator.Execute(
PackageDependencyInfoTransform.Transform(
new PackageDependencyInfo
{
Name = ConstantPackageNames.CSdkPackageName,
Version = migrationSettings.SdkPackageVersion
}), migrationRuleInputs.CommonItemGroup);
2016-09-26 21:40:11 -07:00
// Migrate Direct Deps first
MigrateDependencies(
project,
migrationRuleInputs.OutputMSBuildProject,
null,
project.Dependencies,
migrationRuleInputs.ProjectXproj);
2016-10-03 20:10:09 -07:00
MigrationTrace.Instance.WriteLine($"Migrating {targetFrameworks.Count()} target frameworks");
2016-09-26 21:40:11 -07:00
foreach (var targetFramework in targetFrameworks)
{
2016-10-03 20:10:09 -07:00
MigrationTrace.Instance.WriteLine($"Migrating framework {targetFramework.FrameworkName.GetShortFolderName()}");
2016-09-26 21:40:11 -07:00
MigrateImports(migrationRuleInputs.CommonItemGroup, targetFramework);
MigrateDependencies(
project,
migrationRuleInputs.OutputMSBuildProject,
targetFramework.FrameworkName,
2016-10-03 20:10:09 -07:00
targetFramework.Dependencies,
2016-09-26 21:40:11 -07:00
migrationRuleInputs.ProjectXproj);
}
2016-10-05 11:36:23 -07:00
// Tools
MigrateTools(project, migrationRuleInputs.OutputMSBuildProject);
2016-09-26 21:40:11 -07:00
}
private void MigrateImports(ProjectItemGroupElement commonItemGroup, TargetFrameworkInformation targetFramework)
{
var transform = ImportsTransformation.Transform(targetFramework);
if (transform != null)
{
transform.Condition = targetFramework.FrameworkName.GetMSBuildCondition();
_transformApplicator.Execute(transform, commonItemGroup);
}
}
private void CleanExistingPackageReferences(ProjectRootElement outputMSBuildProject)
{
var packageRefs = outputMSBuildProject.Items.Where(i => i.ItemType == "PackageReference").ToList();
foreach (var packageRef in packageRefs)
{
var parent = packageRef.Parent;
packageRef.Parent.RemoveChild(packageRef);
parent.RemoveIfEmpty();
}
}
2016-10-05 11:36:23 -07:00
private void MigrateTools(
Project project,
ProjectRootElement output)
{
if (project.Tools == null || !project.Tools.Any())
{
return;
}
var itemGroup = output.AddItemGroup();
foreach (var tool in project.Tools)
{
_transformApplicator.Execute(ToolTransform.Transform(tool), itemGroup);
}
}
2016-09-26 21:40:11 -07:00
private void MigrateDependencies(
Project project,
ProjectRootElement output,
NuGetFramework framework,
IEnumerable<ProjectLibraryDependency> dependencies,
ProjectRootElement xproj)
{
var projectDependencies = new HashSet<string>(GetAllProjectReferenceNames(project, framework, xproj));
var packageDependencies = dependencies.Where(d => !projectDependencies.Contains(d.Name));
string condition = framework?.GetMSBuildCondition() ?? "";
var itemGroup = output.ItemGroups.FirstOrDefault(i => i.Condition == condition)
?? output.AddItemGroup();
itemGroup.Condition = condition;
foreach (var packageDependency in packageDependencies)
{
2016-10-03 20:10:09 -07:00
MigrationTrace.Instance.WriteLine(packageDependency.Name);
2016-09-26 21:40:11 -07:00
AddItemTransform<ProjectLibraryDependency> transform;
if (packageDependency.LibraryRange.TypeConstraint == LibraryDependencyTarget.Reference)
{
transform = FrameworkDependencyTransform;
}
else
{
transform = PackageDependencyTransform();
if (packageDependency.Type == LibraryDependencyType.Build)
{
Console.WriteLine("Build type!!!");
transform = transform.WithMetadata("PrivateAssets", "all");
}
else if (packageDependency.SuppressParent != LibraryIncludeFlagUtils.DefaultSuppressParent)
{
var metadataValue = ReadLibraryIncludeFlags(packageDependency.SuppressParent);
transform = transform.WithMetadata("PrivateAssets", metadataValue);
}
if (packageDependency.IncludeType != LibraryIncludeFlags.All)
{
var metadataValue = ReadLibraryIncludeFlags(packageDependency.IncludeType);
transform = transform.WithMetadata("IncludeAssets", metadataValue);
}
}
_transformApplicator.Execute(transform.Transform(packageDependency), itemGroup);
}
}
private string ReadLibraryIncludeFlags(LibraryIncludeFlags includeFlags)
{
if ((includeFlags & LibraryIncludeFlags.All) == LibraryIncludeFlags.All)
{
return "All";
}
var flagString = "";
var allFlagsAndNames = new List<Tuple<string, LibraryIncludeFlags>>
{
Tuple.Create("Analyzers", LibraryIncludeFlags.Analyzers),
Tuple.Create("Build", LibraryIncludeFlags.Build),
Tuple.Create("Compile", LibraryIncludeFlags.Compile),
Tuple.Create("ContentFiles", LibraryIncludeFlags.ContentFiles),
Tuple.Create("Native", LibraryIncludeFlags.Native),
Tuple.Create("Runtime", LibraryIncludeFlags.Runtime)
};
foreach (var flagAndName in allFlagsAndNames)
{
var name = flagAndName.Item1;
var flag = flagAndName.Item2;
if ((includeFlags & flag) == flag)
{
if (!string.IsNullOrEmpty(flagString))
{
flagString += ";";
}
flagString += name;
}
}
return flagString;
}
private IEnumerable<string> GetAllProjectReferenceNames(Project project, NuGetFramework framework, ProjectRootElement xproj)
{
var csprojReferenceItems = _projectDependencyFinder.ResolveXProjProjectDependencies(xproj);
var migratedXProjDependencyPaths = csprojReferenceItems.SelectMany(p => p.Includes());
var migratedXProjDependencyNames = new HashSet<string>(migratedXProjDependencyPaths.Select(p => Path.GetFileNameWithoutExtension(
PathUtility.GetPathWithDirectorySeparator(p))));
var projectDependencies = _projectDependencyFinder.ResolveProjectDependenciesForFramework(
project,
framework,
preResolvedProjects: migratedXProjDependencyNames);
return projectDependencies.Select(p => p.Name).Concat(migratedXProjDependencyNames);
}
private AddItemTransform<ProjectLibraryDependency> FrameworkDependencyTransform => new AddItemTransform<ProjectLibraryDependency>(
"Reference",
dep => dep.Name,
dep => "",
dep => true);
private Func<AddItemTransform<ProjectLibraryDependency>> PackageDependencyTransform => () => new AddItemTransform<ProjectLibraryDependency>(
"PackageReference",
dep => dep.Name,
dep => "",
dep => true)
.WithMetadata("Version", r => r.LibraryRange.VersionRange.OriginalString);
private AddItemTransform<PackageDependencyInfo> PackageDependencyInfoTransform => new AddItemTransform<PackageDependencyInfo>(
"PackageReference",
dep => dep.Name,
dep => "",
dep => true)
.WithMetadata("Version", r => r.Version);
2016-10-05 11:36:23 -07:00
private AddItemTransform<ProjectLibraryDependency> ToolTransform => new AddItemTransform<ProjectLibraryDependency>(
"DotNetCliToolsReference",
dep => dep.Name,
dep => "",
dep => true)
.WithMetadata("Version", r => r.LibraryRange.VersionRange.OriginalString);
2016-09-26 21:40:11 -07:00
private AddItemTransform<TargetFrameworkInformation> ImportsTransformation => new AddItemTransform<TargetFrameworkInformation>(
"PackageTargetFallback",
t => $"$(PackageTargetFallback);{string.Join(";", t.Imports)}",
t => "",
2016-10-03 20:10:09 -07:00
t => t.Imports.OrEmptyIfNull().Any());
2016-09-26 21:40:11 -07:00
private class PackageDependencyInfo
{
public string Name {get; set;}
public string Version {get; set;}
}
}
}