Project Migration Report

This commit is contained in:
Bryan Thornbury 2016-10-04 14:59:04 -07:00
parent 28bd507f40
commit fbaf9a679e
12 changed files with 342 additions and 128 deletions

View file

@ -20,7 +20,7 @@ namespace Microsoft.DotNet.ProjectJsonMigration
public void Throw() public void Throw()
{ {
throw new MigrationException(GetFormattedErrorMessage()); throw new MigrationException(this, GetFormattedErrorMessage());
} }
public string GetFormattedErrorMessage() public string GetFormattedErrorMessage()

View file

@ -7,6 +7,10 @@ namespace Microsoft.DotNet.ProjectJsonMigration
{ {
public class MigrationException : Exception public class MigrationException : Exception
{ {
public MigrationException(string message) : base(message) { } public MigrationError Error { get; }
public MigrationException(MigrationError error, string message) : base(message)
{
Error = error;
}
} }
} }

View file

@ -0,0 +1,21 @@
// 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 Microsoft.Build.Construction;
using System.Linq;
using Microsoft.DotNet.ProjectModel;
using System.IO;
namespace Microsoft.DotNet.ProjectJsonMigration
{
public static class ProjectContextExtensions
{
public static string GetProjectName(this ProjectContext projectContext)
{
// _ here is just an arbitrary configuration value so we can obtain the output name
return Path.GetFileNameWithoutExtension(projectContext.GetOutputPaths("_").CompilationFiles.Assembly);
}
}
}

View file

@ -26,40 +26,47 @@ namespace Microsoft.DotNet.ProjectJsonMigration
_ruleSet = ruleSet; _ruleSet = ruleSet;
} }
public void Migrate(MigrationSettings rootSettings, bool skipProjectReferences = false) public MigrationReport Migrate(MigrationSettings rootSettings, bool skipProjectReferences = false)
{ {
if (rootSettings == null) if (rootSettings == null)
{ {
throw new ArgumentNullException(); throw new ArgumentNullException();
} }
Exception exc = null;
// Try to read the project dependencies, ignore an unresolved exception for now
MigrationRuleInputs rootInputs = ComputeMigrationRuleInputs(rootSettings);
IEnumerable<ProjectDependency> projectDependencies = null; IEnumerable<ProjectDependency> projectDependencies = null;
var tempMSBuildProjectTemplate = rootSettings.MSBuildProjectTemplate.DeepClone(); var tempMSBuildProjectTemplate = rootSettings.MSBuildProjectTemplate.DeepClone();
try try
{ {
// Verify up front so we can prefer these errors over an unresolved project dependency
VerifyInputs(rootInputs, rootSettings);
projectDependencies = ResolveTransitiveClosureProjectDependencies( projectDependencies = ResolveTransitiveClosureProjectDependencies(
rootSettings.ProjectDirectory, rootSettings.ProjectDirectory,
rootSettings.ProjectXProjFilePath); rootSettings.ProjectXProjFilePath);
} }
catch (Exception e) catch (MigrationException e)
{ {
exc = e; return new MigrationReport(
new List<ProjectMigrationReport>
{
new ProjectMigrationReport(
rootSettings.ProjectDirectory,
rootInputs?.DefaultProjectContext.GetProjectName(),
new List<MigrationError> {e.Error},
null)
});
} }
// Verify up front so we can prefer these errors over an unresolved project dependency var projectMigrationReports = new List<ProjectMigrationReport>();
VerifyInputs(ComputeMigrationRuleInputs(rootSettings), rootSettings); projectMigrationReports.Add(MigrateProject(rootSettings));
if (exc != null)
{
throw exc;
}
MigrateProject(rootSettings);
if (skipProjectReferences) if (skipProjectReferences)
{ {
return; return new MigrationReport(projectMigrationReports);
} }
foreach(var project in projectDependencies) foreach(var project in projectDependencies)
@ -70,7 +77,10 @@ namespace Microsoft.DotNet.ProjectJsonMigration
rootSettings.SdkPackageVersion, rootSettings.SdkPackageVersion,
tempMSBuildProjectTemplate); tempMSBuildProjectTemplate);
MigrateProject(settings); MigrateProject(settings);
projectMigrationReports.Add(MigrateProject(settings));
} }
return new MigrationReport(projectMigrationReports);
} }
private void DeleteProjectJsons(MigrationSettings rootsettings, IEnumerable<ProjectDependency> projectDependencies) private void DeleteProjectJsons(MigrationSettings rootsettings, IEnumerable<ProjectDependency> projectDependencies)
@ -118,22 +128,37 @@ namespace Microsoft.DotNet.ProjectJsonMigration
return projectsMap; return projectsMap;
} }
private void MigrateProject(MigrationSettings migrationSettings) private ProjectMigrationReport MigrateProject(MigrationSettings migrationSettings)
{ {
var migrationRuleInputs = ComputeMigrationRuleInputs(migrationSettings); var migrationRuleInputs = ComputeMigrationRuleInputs(migrationSettings);
var projectName = migrationRuleInputs.DefaultProjectContext.GetProjectName();
if (IsMigrated(migrationSettings, migrationRuleInputs)) try
{ {
// TODO : Adding user-visible logging if (IsMigrated(migrationSettings, migrationRuleInputs))
MigrationTrace.Instance.WriteLine($"{nameof(ProjectMigrator)}: Skip migrating {migrationSettings.ProjectDirectory}, it is already migrated."); {
return; MigrationTrace.Instance.WriteLine($"{nameof(ProjectMigrator)}: Skip migrating {migrationSettings.ProjectDirectory}, it is already migrated.");
return new ProjectMigrationReport(migrationSettings.ProjectDirectory, projectName, skipped: true);
}
VerifyInputs(migrationRuleInputs, migrationSettings);
SetupOutputDirectory(migrationSettings.ProjectDirectory, migrationSettings.OutputDirectory);
_ruleSet.Apply(migrationSettings, migrationRuleInputs);
} }
catch (MigrationException exc)
{
var error = new List<MigrationError>
{
exc.Error
};
VerifyInputs(migrationRuleInputs, migrationSettings); return new ProjectMigrationReport(migrationSettings.ProjectDirectory, projectName, error, null);
}
SetupOutputDirectory(migrationSettings.ProjectDirectory, migrationSettings.OutputDirectory);
var outputProject = Path.Combine(migrationSettings.OutputDirectory, projectName + ".csproj");
_ruleSet.Apply(migrationSettings, migrationRuleInputs); return new ProjectMigrationReport(migrationSettings.ProjectDirectory, projectName, outputProject, null);
} }
private MigrationRuleInputs ComputeMigrationRuleInputs(MigrationSettings migrationSettings) private MigrationRuleInputs ComputeMigrationRuleInputs(MigrationSettings migrationSettings)
@ -230,8 +255,7 @@ namespace Microsoft.DotNet.ProjectJsonMigration
public bool IsMigrated(MigrationSettings migrationSettings, MigrationRuleInputs migrationRuleInputs) public bool IsMigrated(MigrationSettings migrationSettings, MigrationRuleInputs migrationRuleInputs)
{ {
var outputName = Path.GetFileNameWithoutExtension( var outputName = migrationRuleInputs.DefaultProjectContext.GetProjectName();
migrationRuleInputs.DefaultProjectContext.GetOutputPaths("_").CompilationFiles.Assembly);
var outputProject = Path.Combine(migrationSettings.OutputDirectory, outputName + ".csproj"); var outputProject = Path.Combine(migrationSettings.OutputDirectory, outputName + ".csproj");
return File.Exists(outputProject); return File.Exists(outputProject);

View file

@ -0,0 +1,65 @@
// 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.Linq;
namespace Microsoft.DotNet.ProjectJsonMigration
{
/// Any changes to this need to be reflected in roslyn-project-system
/// TODO add link
public class MigrationReport
{
public List<ProjectMigrationReport> ProjectMigrationReports { get; }
public int MigratedProjectsCount => ProjectMigrationReports.Count;
public int SucceededProjectsCount => ProjectMigrationReports.Count(p => p.Succeeded);
public int FailedProjectsCount => ProjectMigrationReports.Count(p => p.Failed);
public bool AllSucceeded => ! ProjectMigrationReports.Any(p => p.Failed);
public MigrationReport Merge(MigrationReport otherReport)
{
var allReports = ProjectMigrationReports.Concat(otherReport.ProjectMigrationReports).ToList();
var dedupedReports = DedupeSkippedReports(allReports);
return new MigrationReport(dedupedReports);
}
private List<ProjectMigrationReport> DedupeSkippedReports(List<ProjectMigrationReport> allReports)
{
var reportDict = new Dictionary<string, ProjectMigrationReport>();
foreach (var report in allReports)
{
ProjectMigrationReport existingReport;
if (reportDict.TryGetValue(report.ProjectDirectory, out existingReport))
{
if (existingReport.Skipped)
{
reportDict[report.ProjectDirectory] = report;
}
else if (!report.Skipped)
{
MigrationTrace.Instance.WriteLine("Detected double project migration: {report.ProjectDirectory}");
}
}
else
{
reportDict[report.ProjectDirectory] = report;
}
}
return reportDict.Values.ToList();
}
public MigrationReport(List<ProjectMigrationReport> projectMigrationReports)
{
ProjectMigrationReports = projectMigrationReports;
}
}
}

View file

@ -0,0 +1,45 @@
// 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.Collections.Generic;
using System.Linq;
namespace Microsoft.DotNet.ProjectJsonMigration
{
public class ProjectMigrationReport
{
public string ProjectDirectory { get; }
public string ProjectName { get; }
public string OutputMSBuildProject { get; }
public List<MigrationError> Errors { get; }
public List<string> Warnings { get; }
public bool Skipped { get; }
public bool Failed => Errors.Any();
public bool Succeeded => !Errors.Any();
public ProjectMigrationReport(string projectDirectory, string projectName, bool skipped)
: this(projectDirectory, projectName, null, null, null, skipped: skipped) { }
public ProjectMigrationReport(string projectDirectory, string projectName, List<MigrationError> errors, List<string> warnings)
: this(projectDirectory, projectName, null, errors, warnings) { }
public ProjectMigrationReport(string projectDirectory, string projectName, string outputMSBuildProject, List<string> warnings)
: this(projectDirectory, projectName, outputMSBuildProject, null, warnings) { }
private ProjectMigrationReport(string projectDirectory, string projectName, string outputMSBuildProject, List<MigrationError> errors, List<string> warnings, bool skipped=false)
{
ProjectDirectory = projectDirectory;
ProjectName = projectName;
OutputMSBuildProject = outputMSBuildProject;
Errors = errors ?? new List<MigrationError>();
Warnings = warnings ?? new List<string>();
Skipped=skipped;
}
}
}

View file

@ -9,7 +9,6 @@ using Microsoft.Build.Construction;
using Microsoft.DotNet.Cli.Utils; using Microsoft.DotNet.Cli.Utils;
using Microsoft.DotNet.ProjectJsonMigration.Transforms; using Microsoft.DotNet.ProjectJsonMigration.Transforms;
using Microsoft.DotNet.ProjectModel; using Microsoft.DotNet.ProjectModel;
using Microsoft.DotNet.ProjectModel.Graph;
using Microsoft.DotNet.Tools.Common; using Microsoft.DotNet.Tools.Common;
using NuGet.Frameworks; using NuGet.Frameworks;
using NuGet.LibraryModel; using NuGet.LibraryModel;
@ -142,7 +141,6 @@ namespace Microsoft.DotNet.ProjectJsonMigration.Rules
transform = PackageDependencyTransform(); transform = PackageDependencyTransform();
if (packageDependency.Type == LibraryDependencyType.Build) if (packageDependency.Type == LibraryDependencyType.Build)
{ {
Console.WriteLine("Build type!!!");
transform = transform.WithMetadata("PrivateAssets", "all"); transform = transform.WithMetadata("PrivateAssets", "all");
} }
else if (packageDependency.SuppressParent != LibraryIncludeFlagUtils.DefaultSuppressParent) else if (packageDependency.SuppressParent != LibraryIncludeFlagUtils.DefaultSuppressParent)

View file

@ -10,8 +10,7 @@ namespace Microsoft.DotNet.ProjectJsonMigration.Rules
{ {
public void Apply(MigrationSettings migrationSettings, MigrationRuleInputs migrationRuleInputs) public void Apply(MigrationSettings migrationSettings, MigrationRuleInputs migrationRuleInputs)
{ {
var outputName = Path.GetFileNameWithoutExtension( var outputName = migrationRuleInputs.DefaultProjectContext.GetProjectName();
migrationRuleInputs.DefaultProjectContext.GetOutputPaths("_").CompilationFiles.Assembly);
var outputProject = Path.Combine(migrationSettings.OutputDirectory, outputName + ".csproj"); var outputProject = Path.Combine(migrationSettings.OutputDirectory, outputName + ".csproj");

View file

@ -5,7 +5,9 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Text;
using Microsoft.Build.Construction; using Microsoft.Build.Construction;
using Microsoft.DotNet.Cli.Utils;
using Microsoft.DotNet.ProjectJsonMigration; using Microsoft.DotNet.ProjectJsonMigration;
using Microsoft.DotNet.ProjectModel; using Microsoft.DotNet.ProjectModel;
@ -18,10 +20,19 @@ namespace Microsoft.DotNet.Tools.Migrate
private readonly string _sdkVersion; private readonly string _sdkVersion;
private readonly string _xprojFilePath; private readonly string _xprojFilePath;
private readonly bool _skipProjectReferences; private readonly bool _skipProjectReferences;
private readonly string _reportFile;
private readonly bool _reportFormatJson;
private readonly TemporaryDotnetNewTemplateProject _temporaryDotnetNewProject; private readonly TemporaryDotnetNewTemplateProject _temporaryDotnetNewProject;
public MigrateCommand(string templateFile, string projectArg, string sdkVersion, string xprojFilePath, bool skipProjectReferences) public MigrateCommand(
string templateFile,
string projectArg,
string sdkVersion,
string xprojFilePath,
string reportFile,
bool skipProjectReferences,
bool reportFormatJson)
{ {
_templateFile = templateFile; _templateFile = templateFile;
_projectArg = projectArg ?? Directory.GetCurrentDirectory(); _projectArg = projectArg ?? Directory.GetCurrentDirectory();
@ -29,6 +40,8 @@ namespace Microsoft.DotNet.Tools.Migrate
_xprojFilePath = xprojFilePath; _xprojFilePath = xprojFilePath;
_skipProjectReferences = skipProjectReferences; _skipProjectReferences = skipProjectReferences;
_temporaryDotnetNewProject = new TemporaryDotnetNewTemplateProject(); _temporaryDotnetNewProject = new TemporaryDotnetNewTemplateProject();
_reportFile = reportFile;
_reportFormatJson = reportFormatJson;
} }
public int Execute() public int Execute()
@ -42,16 +55,133 @@ namespace Microsoft.DotNet.Tools.Migrate
EnsureNotNull(sdkVersion, "Null Sdk Version"); EnsureNotNull(sdkVersion, "Null Sdk Version");
MigrationReport migrationReport = null;
foreach (var project in projectsToMigrate) foreach (var project in projectsToMigrate)
{ {
Console.WriteLine($"Migrating project {project}..");
var projectDirectory = Path.GetDirectoryName(project); var projectDirectory = Path.GetDirectoryName(project);
var outputDirectory = projectDirectory; var outputDirectory = projectDirectory;
var migrationSettings = new MigrationSettings(projectDirectory, outputDirectory, sdkVersion, msBuildTemplate, _xprojFilePath); var migrationSettings = new MigrationSettings(projectDirectory, outputDirectory, sdkVersion, msBuildTemplate, _xprojFilePath);
new ProjectMigrator().Migrate(migrationSettings, _skipProjectReferences); var projectMigrationReport = new ProjectMigrator().Migrate(migrationSettings, _skipProjectReferences);
if (migrationReport == null)
{
migrationReport = projectMigrationReport;
}
else
{
migrationReport = migrationReport.Merge(projectMigrationReport);
}
} }
return 0; WriteReport(migrationReport);
return migrationReport.FailedProjectsCount;
}
private void WriteReport(MigrationReport migrationReport)
{
if (!string.IsNullOrEmpty(_reportFile))
{
using (var outputTextWriter = GetReportFileOutputTextWriter())
{
outputTextWriter.Write(GetReportContent(migrationReport));
}
}
WriteReportToStdOut(migrationReport);
}
private void WriteReportToStdOut(MigrationReport migrationReport)
{
StringBuilder sb = new StringBuilder();
foreach (var projectMigrationReport in migrationReport.ProjectMigrationReports)
{
var errorContent = GetProjectReportErrorContent(projectMigrationReport, colored: true);
var successContent = GetProjectReportSuccessContent(projectMigrationReport, colored: true);
if (!string.IsNullOrEmpty(errorContent))
{
Reporter.Error.WriteLine(errorContent);
}
else
{
Reporter.Output.WriteLine(successContent);
}
}
Reporter.Output.WriteLine(GetReportSummary(migrationReport));
}
private string GetReportContent(MigrationReport migrationReport, bool colored = false)
{
if (_reportFormatJson)
{
return Newtonsoft.Json.JsonConvert.SerializeObject(migrationReport);
}
StringBuilder sb = new StringBuilder();
foreach (var projectMigrationReport in migrationReport.ProjectMigrationReports)
{
var errorContent = GetProjectReportErrorContent(projectMigrationReport, colored: colored);
var successContent = GetProjectReportSuccessContent(projectMigrationReport, colored: colored);
if (!string.IsNullOrEmpty(errorContent))
{
sb.AppendLine(errorContent);
}
else
{
sb.AppendLine(successContent);
}
}
sb.AppendLine(GetReportSummary(migrationReport));
return sb.ToString();
}
private string GetReportSummary(MigrationReport migrationReport)
{
StringBuilder sb = new StringBuilder();
sb.AppendLine("Summary");
sb.AppendLine($"Total Projects: {migrationReport.MigratedProjectsCount}");
sb.AppendLine($"Succeeded Projects: {migrationReport.SucceededProjectsCount}");
sb.AppendLine($"Failed Projects: {migrationReport.FailedProjectsCount}");
return sb.ToString();
}
private string GetProjectReportSuccessContent(ProjectMigrationReport projectMigrationReport, bool colored)
{
Func<string, string> GreenIfColored = (str) => colored ? str.Green() : str;
return GreenIfColored($"Project {projectMigrationReport.ProjectName} migration succeeded ({projectMigrationReport.ProjectDirectory})");
}
private string GetProjectReportErrorContent(ProjectMigrationReport projectMigrationReport, bool colored)
{
StringBuilder sb = new StringBuilder();
Func<string, string> RedIfColored = (str) => colored ? str.Red() : str;
if (projectMigrationReport.Errors.Any())
{
sb.AppendLine(RedIfColored($"Project {projectMigrationReport.ProjectName} migration failed ({projectMigrationReport.ProjectDirectory})"));
foreach (var error in projectMigrationReport.Errors.Select(e => e.GetFormattedErrorMessage()))
{
sb.AppendLine(RedIfColored(error));
}
}
return sb.ToString();
}
private TextWriter GetReportFileOutputTextWriter()
{
return File.CreateText(_reportFile);
} }
private IEnumerable<string> GetProjectsToMigrate(string projectArg) private IEnumerable<string> GetProjectsToMigrate(string projectArg)

View file

@ -40,6 +40,9 @@ namespace Microsoft.DotNet.Tools.Migrate
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 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); 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);
CommandOption skipProjectReferences = app.Option("-s|--skip-project-references", "Skip migrating project references. By default project references are migrated recursively", CommandOptionType.BoolValue); CommandOption skipProjectReferences = app.Option("-s|--skip-project-references", "Skip migrating project references. By default project references are migrated recursively", CommandOptionType.BoolValue);
CommandOption reportFile = app.Option("-r|--report-file", "Output migration report to a file in addition to the console.", CommandOptionType.SingleValue);
CommandOption structuredReportOutput = app.Option("--format-report-file-json", "Output migration report file as json rather than user messages", CommandOptionType.BoolValue);
app.OnExecute(() => app.OnExecute(() =>
{ {
@ -48,7 +51,9 @@ namespace Microsoft.DotNet.Tools.Migrate
projectArgument.Value, projectArgument.Value,
sdkVersion.Value(), sdkVersion.Value(),
xprojFile.Value(), xprojFile.Value(),
skipProjectReferences.BoolValue.HasValue ? skipProjectReferences.BoolValue.Value : false); reportFile.Value(),
skipProjectReferences.BoolValue.HasValue ? skipProjectReferences.BoolValue.Value : false,
structuredReportOutput.BoolValue.HasValue ? structuredReportOutput.BoolValue.Value : false);
return migrateCommand.Execute(); return migrateCommand.Execute();
}); });

View file

@ -1,80 +0,0 @@
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.DotNet.ProjectJsonMigration;
namespace Microsoft.DotNet.Tools.Migrate
{
/// <summary>
/// Parses select data from a project.json without relying on ProjectModel.
/// Used to parse simple information.
/// </summary>
internal class ProjectJsonParser
{
public string SdkPackageVersion { get; }
public ProjectJsonParser(JObject projectJson)
{
SdkPackageVersion = GetPackageVersion(projectJson, ConstantPackageNames.CSdkPackageName);
}
private string GetPackageVersion(JObject projectJson, string packageName)
{
var sdkPackageNode = SelectJsonNodes(projectJson, property => property.Name == packageName).First();
if (sdkPackageNode.Value.Type == JTokenType.String)
{
return (string)sdkPackageNode.Value;
}
else if (sdkPackageNode.Type == JTokenType.Object)
{
var sdkPackageNodeValue = (JObject)sdkPackageNode.Value;
JToken versionNode;
if (sdkPackageNodeValue.TryGetValue("version", out versionNode))
{
return versionNode.Value<string>();
}
else
{
throw new Exception("Unable to determine sdk version, no version node in default template.");
}
}
else
{
throw new Exception("Unable to determine sdk version, no version information found");
}
}
private IEnumerable<JProperty> SelectJsonNodes(
JToken jsonNode,
Func<JProperty, bool> condition,
List<JProperty> nodeAccumulator = null)
{
nodeAccumulator = nodeAccumulator ?? new List<JProperty>();
if (jsonNode.Type == JTokenType.Object)
{
var eligibleNodes = jsonNode.Children<JProperty>().Where(j => condition(j));
nodeAccumulator.AddRange(eligibleNodes);
foreach (var child in jsonNode.Children<JProperty>())
{
SelectJsonNodes(child.Value, condition, nodeAccumulator: nodeAccumulator);
}
}
else if (jsonNode.Type == JTokenType.Array)
{
foreach (var child in jsonNode.Children())
{
SelectJsonNodes(child, condition, nodeAccumulator: nodeAccumulator);
}
}
return nodeAccumulator;
}
}
}

View file

@ -37,7 +37,7 @@ namespace Microsoft.DotNet.ProjectJsonMigration.Tests
} }
[Fact] [Fact]
public void It_throws_when_migrating_a_deprecated_projectJson() public void It_has_error_when_migrating_a_deprecated_projectJson()
{ {
var testProjectDirectory = var testProjectDirectory =
TestAssetsManager.CreateTestInstance("TestLibraryWithDeprecatedProjectFile", callingMethod: "z") TestAssetsManager.CreateTestInstance("TestLibraryWithDeprecatedProjectFile", callingMethod: "z")
@ -47,16 +47,18 @@ namespace Microsoft.DotNet.ProjectJsonMigration.Tests
var testSettings = new MigrationSettings(testProjectDirectory, testProjectDirectory, "1.0.0", mockProj); var testSettings = new MigrationSettings(testProjectDirectory, testProjectDirectory, "1.0.0", mockProj);
var projectMigrator = new ProjectMigrator(new FakeEmptyMigrationRule()); var projectMigrator = new ProjectMigrator(new FakeEmptyMigrationRule());
Action migrateAction = () => projectMigrator.Migrate(testSettings); var report = projectMigrator.Migrate(testSettings);
migrateAction.ShouldThrow<Exception>().Where( var projectReport = report.ProjectMigrationReports.First();
e => e.Message.Contains("MIGRATE1011::Deprecated Project:")
&& e.Message.Contains("The 'packInclude' option is deprecated. Use 'files' in 'packOptions' instead. (line: 6, file:") var errorMessage = projectReport.Errors.First().GetFormattedErrorMessage();
&& e.Message.Contains("The 'compilationOptions' option is deprecated. Use 'buildOptions' instead. (line: 3, file:")); errorMessage.Should().Contain("MIGRATE1011::Deprecated Project:");
errorMessage.Should().Contain("The 'packInclude' option is deprecated. Use 'files' in 'packOptions' instead. (line: 6, file:");
errorMessage.Should().Contain("The 'compilationOptions' option is deprecated. Use 'buildOptions' instead. (line: 3, file:");
} }
[Fact] [Fact]
public void It_throws_when_migrating_a_non_csharp_app() public void It_has_error_when_migrating_a_non_csharp_app()
{ {
var testProjectDirectory = var testProjectDirectory =
TestAssetsManager.CreateTestInstance("FSharpTestProjects/TestApp", callingMethod: "z") TestAssetsManager.CreateTestInstance("FSharpTestProjects/TestApp", callingMethod: "z")
@ -66,10 +68,11 @@ namespace Microsoft.DotNet.ProjectJsonMigration.Tests
var testSettings = new MigrationSettings(testProjectDirectory, testProjectDirectory, "1.0.0", mockProj); var testSettings = new MigrationSettings(testProjectDirectory, testProjectDirectory, "1.0.0", mockProj);
var projectMigrator = new ProjectMigrator(new FakeEmptyMigrationRule()); var projectMigrator = new ProjectMigrator(new FakeEmptyMigrationRule());
Action migrateAction = () => projectMigrator.Migrate(testSettings); var report = projectMigrator.Migrate(testSettings);
var projectReport = report.ProjectMigrationReports.First();
migrateAction.ShouldThrow<Exception>().Where( var errorMessage = projectReport.Errors.First().GetFormattedErrorMessage();
e => e.Message.Contains("MIGRATE20013::Non-Csharp App: Cannot migrate project")); errorMessage.Should().Contain("MIGRATE20013::Non-Csharp App: Cannot migrate project");
} }
private IEnumerable<string> EnumerateFilesWithRelativePath(string testProjectDirectory) private IEnumerable<string> EnumerateFilesWithRelativePath(string testProjectDirectory)