Skip to content
This repository was archived by the owner on Apr 20, 2023. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ public MigrationError(string errorCode, string generalErrorReason, string messag

public void Throw()
{
throw new MigrationException(GetFormattedErrorMessage());
throw new MigrationException(this, GetFormattedErrorMessage());
}

public string GetFormattedErrorMessage()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ namespace Microsoft.DotNet.ProjectJsonMigration
{
public class MigrationException : Exception
{
public MigrationException(string message) : base(message) { }
public MigrationError Error { get; }
public MigrationException(MigrationError error, string message) : base(message)
{
Error = error;
}
}
}
Original file line number Diff line number Diff line change
@@ -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);

This comment was marked as spam.

This comment was marked as spam.

This comment was marked as spam.

This comment was marked as spam.

This comment was marked as spam.

This comment was marked as spam.

}
}
}
76 changes: 50 additions & 26 deletions src/Microsoft.DotNet.ProjectJsonMigration/ProjectMigrator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,40 +26,47 @@ public ProjectMigrator(IMigrationRule ruleSet)
_ruleSet = ruleSet;
}

public void Migrate(MigrationSettings rootSettings, bool skipProjectReferences = false)
public MigrationReport Migrate(MigrationSettings rootSettings, bool skipProjectReferences = false)
{
if (rootSettings == null)
{
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;

var tempMSBuildProjectTemplate = rootSettings.MSBuildProjectTemplate.DeepClone();

try
{
// Verify up front so we can prefer these errors over an unresolved project dependency
VerifyInputs(rootInputs, rootSettings);

projectDependencies = ResolveTransitiveClosureProjectDependencies(
rootSettings.ProjectDirectory,
rootSettings.ProjectXProjFilePath);
}
catch (Exception e)
{
exc = e;
}

// Verify up front so we can prefer these errors over an unresolved project dependency
VerifyInputs(ComputeMigrationRuleInputs(rootSettings), rootSettings);
if (exc != null)
catch (MigrationException e)
{
throw exc;
return new MigrationReport(
new List<ProjectMigrationReport>
{
new ProjectMigrationReport(
rootSettings.ProjectDirectory,
rootInputs?.DefaultProjectContext.GetProjectName(),
new List<MigrationError> {e.Error},
null)
});
}

MigrateProject(rootSettings);

var projectMigrationReports = new List<ProjectMigrationReport>();
projectMigrationReports.Add(MigrateProject(rootSettings));

if (skipProjectReferences)
{
return;
return new MigrationReport(projectMigrationReports);
}

foreach(var project in projectDependencies)
Expand All @@ -70,7 +77,10 @@ public void Migrate(MigrationSettings rootSettings, bool skipProjectReferences =
rootSettings.SdkPackageVersion,
tempMSBuildProjectTemplate);
MigrateProject(settings);
projectMigrationReports.Add(MigrateProject(settings));
}

return new MigrationReport(projectMigrationReports);
}

private void DeleteProjectJsons(MigrationSettings rootsettings, IEnumerable<ProjectDependency> projectDependencies)
Expand Down Expand Up @@ -118,22 +128,37 @@ private IEnumerable<ProjectDependency> ResolveTransitiveClosureProjectDependenci
return projectsMap;
}

private void MigrateProject(MigrationSettings migrationSettings)
private ProjectMigrationReport MigrateProject(MigrationSettings migrationSettings)
{
var migrationRuleInputs = ComputeMigrationRuleInputs(migrationSettings);
var projectName = migrationRuleInputs.DefaultProjectContext.GetProjectName();

if (IsMigrated(migrationSettings, migrationRuleInputs))
{
// TODO : Adding user-visible logging
MigrationTrace.Instance.WriteLine($"{nameof(ProjectMigrator)}: Skip migrating {migrationSettings.ProjectDirectory}, it is already migrated.");
return;
}
try
{
if (IsMigrated(migrationSettings, migrationRuleInputs))
{
MigrationTrace.Instance.WriteLine($"{nameof(ProjectMigrator)}: Skip migrating {migrationSettings.ProjectDirectory}, it is already migrated.");
return new ProjectMigrationReport(migrationSettings.ProjectDirectory, projectName, skipped: true);
}

VerifyInputs(migrationRuleInputs, migrationSettings);

VerifyInputs(migrationRuleInputs, migrationSettings);
SetupOutputDirectory(migrationSettings.ProjectDirectory, migrationSettings.OutputDirectory);

SetupOutputDirectory(migrationSettings.ProjectDirectory, migrationSettings.OutputDirectory);
_ruleSet.Apply(migrationSettings, migrationRuleInputs);
}
catch (MigrationException exc)
{
var error = new List<MigrationError>
{
exc.Error
};

_ruleSet.Apply(migrationSettings, migrationRuleInputs);
return new ProjectMigrationReport(migrationSettings.ProjectDirectory, projectName, error, null);
}

var outputProject = Path.Combine(migrationSettings.OutputDirectory, projectName + ".csproj");
return new ProjectMigrationReport(migrationSettings.ProjectDirectory, projectName, outputProject, null);
}

private MigrationRuleInputs ComputeMigrationRuleInputs(MigrationSettings migrationSettings)
Expand Down Expand Up @@ -230,8 +255,7 @@ private void CopyProjectToOutputDirectory(string projectDirectory, string output

public bool IsMigrated(MigrationSettings migrationSettings, MigrationRuleInputs migrationRuleInputs)
{
var outputName = Path.GetFileNameWithoutExtension(
migrationRuleInputs.DefaultProjectContext.GetOutputPaths("_").CompilationFiles.Assembly);
var outputName = migrationRuleInputs.DefaultProjectContext.GetProjectName();

var outputProject = Path.Combine(migrationSettings.OutputDirectory, outputName + ".csproj");
return File.Exists(outputProject);
Expand Down
Original file line number Diff line number Diff line change
@@ -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;
}
}
}
Original file line number Diff line number Diff line change
@@ -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

This comment was marked as spam.

This comment was marked as spam.

This comment was marked as spam.

This comment was marked as spam.

{
public string ProjectDirectory { get; }

public string ProjectName { get; }

public string OutputMSBuildProject { get; }

public List<MigrationError> Errors { get; }

public List<string> Warnings { get; }

This comment was marked as spam.

This comment was marked as spam.


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;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
using Microsoft.DotNet.Cli.Utils;
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;
Expand Down Expand Up @@ -142,7 +141,6 @@ private void MigrateDependencies(
transform = PackageDependencyTransform();
if (packageDependency.Type == LibraryDependencyType.Build)
{
Console.WriteLine("Build type!!!");
transform = transform.WithMetadata("PrivateAssets", "all");
}
else if (packageDependency.SuppressParent != LibraryIncludeFlagUtils.DefaultSuppressParent)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,7 @@ public class SaveOutputProjectRule : IMigrationRule
{
public void Apply(MigrationSettings migrationSettings, MigrationRuleInputs migrationRuleInputs)
{
var outputName = Path.GetFileNameWithoutExtension(
migrationRuleInputs.DefaultProjectContext.GetOutputPaths("_").CompilationFiles.Assembly);
var outputName = migrationRuleInputs.DefaultProjectContext.GetProjectName();

var outputProject = Path.Combine(migrationSettings.OutputDirectory, outputName + ".csproj");

Expand Down
Loading