Migrate xproj to csproj dependencies
This commit is contained in:
parent
08fbe7f9d1
commit
5d2f0579d2
14 changed files with 166 additions and 35 deletions
|
@ -1,4 +1,6 @@
|
|||
using System;
|
||||
// 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;
|
||||
|
||||
namespace Microsoft.DotNet.ProjectJsonMigration
|
||||
{
|
||||
|
@ -19,7 +21,7 @@ namespace Microsoft.DotNet.ProjectJsonMigration
|
|||
|
||||
public void Throw()
|
||||
{
|
||||
throw new Exception(GetFormattedErrorMessage());
|
||||
throw new MigrationException(GetFormattedErrorMessage());
|
||||
}
|
||||
|
||||
public string GetFormattedErrorMessage()
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
using System;
|
||||
// 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;
|
||||
|
||||
namespace Microsoft.DotNet.ProjectJsonMigration
|
||||
{
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
// 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;
|
||||
|
||||
namespace Microsoft.DotNet.ProjectJsonMigration
|
||||
{
|
||||
public class MigrationException : Exception
|
||||
{
|
||||
public MigrationException(string message) : base(message) { }
|
||||
}
|
||||
}
|
|
@ -15,6 +15,8 @@ namespace Microsoft.DotNet.ProjectJsonMigration
|
|||
{
|
||||
public class MigrationRuleInputs
|
||||
{
|
||||
public ProjectRootElement ProjectXproj { get; }
|
||||
|
||||
public ProjectRootElement OutputMSBuildProject { get; }
|
||||
|
||||
public ProjectItemGroupElement CommonItemGroup { get; }
|
||||
|
@ -35,8 +37,10 @@ namespace Microsoft.DotNet.ProjectJsonMigration
|
|||
IEnumerable<ProjectContext> projectContexts,
|
||||
ProjectRootElement outputMSBuildProject,
|
||||
ProjectItemGroupElement commonItemGroup,
|
||||
ProjectPropertyGroupElement commonPropertyGroup)
|
||||
ProjectPropertyGroupElement commonPropertyGroup,
|
||||
ProjectRootElement projectXproj=null)
|
||||
{
|
||||
ProjectXproj = projectXproj;
|
||||
ProjectContexts = projectContexts;
|
||||
OutputMSBuildProject = outputMSBuildProject;
|
||||
CommonItemGroup = commonItemGroup;
|
||||
|
|
|
@ -15,21 +15,24 @@ namespace Microsoft.DotNet.ProjectJsonMigration
|
|||
{
|
||||
public class MigrationSettings
|
||||
{
|
||||
public string ProjectXProjFilePath { get; }
|
||||
public string ProjectDirectory { get; }
|
||||
public string OutputDirectory { get; }
|
||||
public string SdkPackageVersion { get; }
|
||||
public ProjectRootElement MSBuildProjectTemplate { get; }
|
||||
|
||||
|
||||
public MigrationSettings(
|
||||
string projectDirectory,
|
||||
string outputDirectory,
|
||||
string sdkPackageVersion,
|
||||
ProjectRootElement msBuildProjectTemplate)
|
||||
ProjectRootElement msBuildProjectTemplate,
|
||||
string projectXprojFilePath=null)
|
||||
{
|
||||
ProjectDirectory = projectDirectory;
|
||||
OutputDirectory = outputDirectory;
|
||||
SdkPackageVersion = sdkPackageVersion;
|
||||
MSBuildProjectTemplate = msBuildProjectTemplate;
|
||||
ProjectXProjFilePath = projectXprojFilePath;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
using System;
|
||||
// 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.Text.RegularExpressions;
|
||||
|
||||
namespace Microsoft.DotNet.ProjectJsonMigration
|
||||
|
|
|
@ -46,6 +46,13 @@ namespace Microsoft.DotNet.ProjectJsonMigration
|
|||
private MigrationRuleInputs ComputeMigrationRuleInputs(MigrationSettings migrationSettings)
|
||||
{
|
||||
var projectContexts = ProjectContext.CreateContextForEachFramework(migrationSettings.ProjectDirectory);
|
||||
var xprojFile = migrationSettings.ProjectXProjFilePath ?? FindXprojFile(migrationSettings.ProjectDirectory);
|
||||
|
||||
ProjectRootElement xproj = null;
|
||||
if (xprojFile != null)
|
||||
{
|
||||
xproj = ProjectRootElement.Open(xprojFile);
|
||||
}
|
||||
|
||||
var templateMSBuildProject = migrationSettings.MSBuildProjectTemplate;
|
||||
if (templateMSBuildProject == null)
|
||||
|
@ -56,7 +63,19 @@ namespace Microsoft.DotNet.ProjectJsonMigration
|
|||
var propertyGroup = templateMSBuildProject.AddPropertyGroup();
|
||||
var itemGroup = templateMSBuildProject.AddItemGroup();
|
||||
|
||||
return new MigrationRuleInputs(projectContexts, templateMSBuildProject, itemGroup, propertyGroup);
|
||||
return new MigrationRuleInputs(projectContexts, templateMSBuildProject, itemGroup, propertyGroup, xproj);
|
||||
}
|
||||
|
||||
private string FindXprojFile(string projectDirectory)
|
||||
{
|
||||
var allXprojFiles = Directory.EnumerateFiles(projectDirectory, "*.xproj", SearchOption.TopDirectoryOnly);
|
||||
|
||||
if (allXprojFiles.Count() > 1)
|
||||
{
|
||||
throw new Exception("Multiple xproj files found in {projectDirectory}, please specify which to use");
|
||||
}
|
||||
|
||||
return allXprojFiles.FirstOrDefault();
|
||||
}
|
||||
|
||||
private void VerifyInputs(MigrationRuleInputs migrationRuleInputs, MigrationSettings migrationSettings)
|
||||
|
|
|
@ -12,9 +12,7 @@ using Newtonsoft.Json.Linq;
|
|||
using NuGet.Frameworks;
|
||||
|
||||
namespace Microsoft.DotNet.ProjectJsonMigration.Rules
|
||||
{
|
||||
// TODO: Should All build options be protected by a configuration condition?
|
||||
// This will prevent the entire merge issue altogether and sidesteps the problem of having a duplicate include with different excludes...
|
||||
{ // TODO: Should All build options be protected by a configuration condition?
|
||||
public class MigrateBuildOptionsRule : IMigrationRule
|
||||
{
|
||||
private AddPropertyTransform<CommonCompilerOptions>[] EmitEntryPointTransforms
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
// 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;
|
||||
|
@ -27,17 +28,75 @@ namespace Microsoft.DotNet.ProjectJsonMigration.Rules
|
|||
{
|
||||
_projectDirectory = migrationSettings.ProjectDirectory;
|
||||
|
||||
var csproj = migrationRuleInputs.OutputMSBuildProject;
|
||||
|
||||
var migratedXProjDependencyPaths = MigrateXProjProjectDependencies(migrationSettings, migrationRuleInputs);
|
||||
var migratedXProjDependencyNames = migratedXProjDependencyPaths.Select(p => Path.GetFileNameWithoutExtension(p));
|
||||
|
||||
MigrateProjectJsonProjectDependencies(migrationSettings, migrationRuleInputs, migratedXProjDependencyNames);
|
||||
}
|
||||
|
||||
private IEnumerable<string> MigrateXProjProjectDependencies(MigrationSettings migrationSettings, MigrationRuleInputs migrationRuleInputs)
|
||||
{
|
||||
var xproj = migrationRuleInputs.ProjectXproj;
|
||||
if (xproj == null)
|
||||
{
|
||||
MigrationTrace.Instance.WriteLine($"{nameof(MigrateProjectDependenciesRule)}: No xproj file given.");
|
||||
return Enumerable.Empty<string>();
|
||||
}
|
||||
|
||||
var projectReferenceItems = xproj.Items.Where(i => i.ItemType == "ProjectReference");
|
||||
|
||||
IEnumerable<string> projectReferences = new List<string>();
|
||||
foreach (var projectReferenceItem in projectReferenceItems)
|
||||
{
|
||||
projectReferences = projectReferences.Union(projectReferenceItem.Includes());
|
||||
}
|
||||
|
||||
var csprojReferences = projectReferences
|
||||
.Where(p => string.Equals(Path.GetExtension(p), ".csproj", StringComparison.OrdinalIgnoreCase));
|
||||
|
||||
MigrationTrace.Instance.WriteLine($"{nameof(MigrateProjectDependenciesRule)}: Migrating {csprojReferences.Count()} xproj to csproj references");
|
||||
|
||||
var csprojReferenceTransforms = csprojReferences.Select(r => ProjectDependencyStringTransform.Transform(r));
|
||||
foreach (var csprojReferenceTransform in csprojReferenceTransforms)
|
||||
{
|
||||
_transformApplicator.Execute(csprojReferenceTransform, migrationRuleInputs.CommonItemGroup);
|
||||
}
|
||||
|
||||
return csprojReferences;
|
||||
}
|
||||
|
||||
public void MigrateProjectJsonProjectDependencies(
|
||||
MigrationSettings migrationSettings,
|
||||
MigrationRuleInputs migrationRuleInputs,
|
||||
IEnumerable<string> migratedXProjDependencyNames)
|
||||
{
|
||||
var outputMSBuildProject = migrationRuleInputs.OutputMSBuildProject;
|
||||
var projectContext = migrationRuleInputs.DefaultProjectContext;
|
||||
var projectExports = projectContext.CreateExporter("_").GetDependencies(LibraryType.Project);
|
||||
|
||||
var projectDependencyTransformResults =
|
||||
projectExports.Select(projectExport => ProjectDependencyTransform.Transform(projectExport));
|
||||
var projectDependencyTransformResults = new List<ProjectItemElement>();
|
||||
foreach (var projectExport in projectExports)
|
||||
{
|
||||
try
|
||||
{
|
||||
projectDependencyTransformResults.Add(ProjectDependencyTransform.Transform(projectExport));
|
||||
}
|
||||
catch (MigrationException unresolvedProjectReferenceException)
|
||||
{
|
||||
if (!migratedXProjDependencyNames.Contains(projectExport.Library.Identity.Name))
|
||||
{
|
||||
throw unresolvedProjectReferenceException;
|
||||
}
|
||||
|
||||
MigrationTrace.Instance.WriteLine($"{nameof(MigrateProjectDependenciesRule)}: Ignoring unresolved project reference {projectExport.Library.Identity.Name} satisfied by xproj to csproj ProjectReference");
|
||||
}
|
||||
}
|
||||
|
||||
if (projectDependencyTransformResults.Any())
|
||||
{
|
||||
AddPropertyTransformsToCommonPropertyGroup(migrationRuleInputs.CommonPropertyGroup);
|
||||
AddProjectDependenciesToNewItemGroup(csproj.AddItemGroup(), projectDependencyTransformResults);
|
||||
AddProjectDependenciesToNewItemGroup(outputMSBuildProject.AddItemGroup(), projectDependencyTransformResults);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -92,5 +151,11 @@ namespace Microsoft.DotNet.ProjectJsonMigration.Rules
|
|||
},
|
||||
export => "",
|
||||
export => true);
|
||||
|
||||
private AddItemTransform<string> ProjectDependencyStringTransform => new AddItemTransform<string>(
|
||||
"ProjectReference",
|
||||
path => path,
|
||||
path => "",
|
||||
path => true);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,12 +0,0 @@
|
|||
using System;
|
||||
|
||||
namespace Microsoft.DotNet.ProjectJsonMigration.Rules
|
||||
{
|
||||
public class MigrateXprojProjectReferencesRule : IMigrationRule
|
||||
{
|
||||
public void Apply(MigrationSettings migrationSettings, MigrationRuleInputs migrationRuleInputs)
|
||||
{
|
||||
throw new NotImplementedException("TODO: XProj ProjectToProject references");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -16,15 +16,17 @@ namespace Microsoft.DotNet.Tools.Migrate
|
|||
private readonly string _outputDirectory;
|
||||
private readonly string _projectJson;
|
||||
private readonly string _sdkVersion;
|
||||
private readonly string _xprojFilePath;
|
||||
|
||||
private readonly TemporaryDotnetNewTemplateProject _temporaryDotnetNewProject;
|
||||
|
||||
public MigrateCommand(string templateFile, string outputDirectory, string projectJson, string sdkVersion)
|
||||
public MigrateCommand(string templateFile, string outputDirectory, string projectJson, string sdkVersion, string xprojFilePath)
|
||||
{
|
||||
_templateFile = templateFile;
|
||||
_outputDirectory = outputDirectory;
|
||||
_projectJson = projectJson;
|
||||
_sdkVersion = sdkVersion;
|
||||
_xprojFilePath = xprojFilePath;
|
||||
|
||||
_temporaryDotnetNewProject = new TemporaryDotnetNewTemplateProject();
|
||||
}
|
||||
|
@ -44,7 +46,7 @@ namespace Microsoft.DotNet.Tools.Migrate
|
|||
var sdkVersion = _sdkVersion ?? new ProjectJsonParser(_temporaryDotnetNewProject.ProjectJson).SdkPackageVersion;
|
||||
EnsureNotNull(sdkVersion, "Null Sdk Version");
|
||||
|
||||
var migrationSettings = new MigrationSettings(projectDirectory, outputDirectory, sdkVersion, msBuildTemplate);
|
||||
var migrationSettings = new MigrationSettings(projectDirectory, outputDirectory, sdkVersion, msBuildTemplate, _xprojFilePath);
|
||||
new ProjectMigrator().Migrate(migrationSettings);
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -24,6 +24,7 @@ namespace Microsoft.DotNet.Tools.Migrate
|
|||
CommandOption output = app.Option("-o|--output", "Directory to output migrated project to. The default is the project directory", CommandOptionType.SingleValue);
|
||||
CommandOption project = app.Option("-p|--project", "The path to the project to run (defaults to the current directory). Can be a path to a project.json or a project directory", CommandOptionType.SingleValue);
|
||||
CommandOption sdkVersion = app.Option("-v|--sdk-package-version", "The version of the sdk package that will be referenced in the migrated app. The default is the version of the sdk in dotnet new -t msbuild", CommandOptionType.SingleValue);
|
||||
CommandOption xprojFile = app.Option("-x|--xproj-file", "The path to the xproj file to use. Required when there is more than one xproj in a project directory.", CommandOptionType.SingleValue);
|
||||
|
||||
app.OnExecute(() =>
|
||||
{
|
||||
|
@ -31,7 +32,8 @@ namespace Microsoft.DotNet.Tools.Migrate
|
|||
template.Value(),
|
||||
output.Value(),
|
||||
project.Value(),
|
||||
sdkVersion.Value());
|
||||
sdkVersion.Value(),
|
||||
xprojFile.Value());
|
||||
|
||||
return migrateCommand.Execute();
|
||||
});
|
||||
|
|
|
@ -53,7 +53,7 @@ namespace Microsoft.DotNet.ProjectJsonMigration.Tests
|
|||
|
||||
var projectContext = ProjectContext.Create(appDirectory, FrameworkConstants.CommonFrameworks.NetCoreApp10);
|
||||
var mockProj = ProjectRootElement.Create();
|
||||
var testSettings = new MigrationSettings(appDirectory, appDirectory, "1.0.0", mockProj);
|
||||
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);
|
||||
|
@ -82,5 +82,37 @@ namespace Microsoft.DotNet.ProjectJsonMigration.Tests
|
|||
action.ShouldThrow<Exception>()
|
||||
.Where(e => e.Message.Contains("MIGRATE1014::Unresolved Dependency: Unresolved project dependency (TestLibrary)"));
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(@"some/path/to.cSproj", new [] { @"some/path/to.cSproj" })]
|
||||
[InlineData(@"to.CSPROJ",new [] { @"to.CSPROJ" })]
|
||||
public void It_migrates_csproj_ProjectReference_in_xproj(string projectReference, string[] expectedMigratedReferences)
|
||||
{
|
||||
var xproj = ProjectRootElement.Create();
|
||||
xproj.AddItem("ProjectReference", projectReference);
|
||||
|
||||
var projectReferenceName = Path.GetFileNameWithoutExtension(projectReference);
|
||||
|
||||
var projectJson = @"
|
||||
{
|
||||
""dependencies"": {" +
|
||||
$"\"{projectReferenceName}\"" + @": {
|
||||
""target"" : ""project""
|
||||
}
|
||||
}
|
||||
}
|
||||
";
|
||||
Console.WriteLine(projectJson);
|
||||
|
||||
var testDirectory = Temp.CreateDirectory().Path;
|
||||
var migratedProj = TemporaryProjectFileRuleRunner.RunRules(new IMigrationRule[]
|
||||
{
|
||||
new MigrateProjectDependenciesRule()
|
||||
}, projectJson, testDirectory, xproj);
|
||||
|
||||
var migratedProjectReferenceItems = migratedProj.Items.Where(i => i.ItemType == "ProjectReference");
|
||||
migratedProjectReferenceItems.Should().HaveCount(expectedMigratedReferences.Length);
|
||||
migratedProjectReferenceItems.Select(m => m.Include).Should().BeEquivalentTo(expectedMigratedReferences);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,10 +9,10 @@ namespace Microsoft.DotNet.ProjectJsonMigration.Tests
|
|||
public class TemporaryProjectFileRuleRunner
|
||||
{
|
||||
public static ProjectRootElement RunRules(IEnumerable<IMigrationRule> rules, string projectJson,
|
||||
string testDirectory)
|
||||
string testDirectory, ProjectRootElement xproj=null)
|
||||
{
|
||||
var projectContext = GenerateProjectContextFromString(testDirectory, projectJson);
|
||||
return RunMigrationRulesOnGeneratedProject(rules, projectContext, testDirectory);
|
||||
return RunMigrationRulesOnGeneratedProject(rules, projectContext, testDirectory, xproj);
|
||||
}
|
||||
|
||||
private static ProjectContext GenerateProjectContextFromString(string projectDirectory, string json)
|
||||
|
@ -25,13 +25,14 @@ namespace Microsoft.DotNet.ProjectJsonMigration.Tests
|
|||
}
|
||||
|
||||
private static ProjectRootElement RunMigrationRulesOnGeneratedProject(IEnumerable<IMigrationRule> rules,
|
||||
ProjectContext projectContext, string testDirectory)
|
||||
ProjectContext projectContext, string testDirectory, ProjectRootElement xproj)
|
||||
{
|
||||
var project = ProjectRootElement.Create();
|
||||
var testSettings = new MigrationSettings(testDirectory, testDirectory, "1.0.0", project);
|
||||
var testInputs = new MigrationRuleInputs(new[] {projectContext}, project,
|
||||
project.AddItemGroup(),
|
||||
project.AddPropertyGroup());
|
||||
project.AddPropertyGroup(),
|
||||
xproj);
|
||||
|
||||
foreach (var rule in rules)
|
||||
{
|
||||
|
|
Loading…
Add table
Reference in a new issue