private void BackupProjects(MigrationReport migrationReport) { foreach (var report in migrationReport.ProjectMigrationReports) { MigrateProject(report); } }
public void VerifyWronglyUsedOfSizeAreReported() { var dataTypes = new List <UsedDataType> { new UsedDataType(new DataType(DbType.Int32, 666, 0), false, false), new UsedDataType(new DataType(DbType.String, 0, 666), false, false), new UsedDataType(new DataType(DbType.Decimal, 0, 0), false, false), }; IRecordedMigration migration = MockRepository.GenerateStub <IRecordedMigration>(); migration.Expect(m => m.DataTypes).Return(dataTypes); migration.Expect(m => m.Methods).Return(Enumerable.Empty <string>()); MigrationReport report = new MigrationReport(MigrationName, string.Empty, migration); string errors; string warnings; Validate(report, out errors, out warnings); Assert.AreEqual( string.Format(CultureInfo.CurrentCulture, "Migration '{0}' uses the data type '{1}(666)' with a non-zero size and a zero scale which is not supported by '{2}'.", MigrationName, DbType.Int32, ProviderName) + Environment.NewLine + string.Format(CultureInfo.CurrentCulture, "Migration '{0}' uses the data type '{1}(0,666)' with a zero size and a non-zero scale which is not supported by '{2}'.", MigrationName, DbType.String, ProviderName) + Environment.NewLine + string.Format(CultureInfo.CurrentCulture, "Migration '{0}' uses the data type '{1}' with a zero size and a zero scale which is not supported by '{2}'.", MigrationName, DbType.Decimal, ProviderName), errors); Assert.IsNullOrEmpty(warnings); }
public void VerifyUnsupportedDataTypesAreReported() { var dataTypes = new List <UsedDataType> { new UsedDataType(new DataType(DbType.String, 255), false, false), // ok new UsedDataType(new DataType(DbType.Currency), false, false), // not supported new UsedDataType(new DataType(DbType.Int32), false, false), // ok new UsedDataType(new DataType(DbType.Decimal, 20, 10), false, false), // exceeds size and scale new UsedDataType(new DataType(DbType.String), false, false), // ok (should not override the primary key status of this DbType) new UsedDataType(new DataType(DbType.String), true, false), // as primary key -> *not* ok w/o size new UsedDataType(new DataType(DbType.String, 255), true, false), // as primary key -> ok new UsedDataType(new DataType(DbType.Decimal, 8, 2), false, true), // as identity -> *not* ok with scale new UsedDataType(new DataType(DbType.Decimal, 8), false, true), // as identity -> ok without scale }; IRecordedMigration migration = A.Fake <IRecordedMigration>(); A.CallTo(() => migration.DataTypes).Returns(dataTypes); //migration.Expect(m => m.Methods).Return(Enumerable.Empty<string>()); MigrationReport report = new MigrationReport(MigrationName, string.Empty, migration); string errors; string warnings; Validate(report, out errors, out warnings); string expected = string.Format(CultureInfo.CurrentCulture, "Migration '{0}' uses the data type '{1}' which is not supported by '{2}'.", MigrationName, DbType.Currency, Platform) + Environment.NewLine + string.Format(CultureInfo.CurrentCulture, "Migration '{0}' uses the data type '{1}(20,10)' which exceeds the maximum size of 10 supported by '{2}'.", MigrationName, DbType.Decimal, Platform) + Environment.NewLine + string.Format(CultureInfo.CurrentCulture, "Migration '{0}' uses the data type '{1}(20,10)' which exceeds the maximum scale of 5 supported by '{2}'.", MigrationName, DbType.Decimal, Platform) + Environment.NewLine + string.Format(CultureInfo.CurrentCulture, "Migration '{0}' uses the data type '{1}' for a primary key which is not supported by '{2}'.", MigrationName, DbType.String, Platform) + Environment.NewLine + string.Format(CultureInfo.CurrentCulture, "Migration '{0}' uses the data type '{1}(8,2)' for an identity column which is not supported by '{2}'.", MigrationName, DbType.Decimal, Platform); Assert.AreEqual(expected, errors); }
public void VerifyWronglyUsedOfSizeAreReported() { var dataTypes = new List <UsedDataType> { new UsedDataType(new DataType(DbType.Int32, 777), false, false), new UsedDataType(new DataType(DbType.String, null, 777), false, false), new UsedDataType(new DataType(DbType.Decimal), false, false), }; IRecordedMigration migration = A.Fake <IRecordedMigration>(); A.CallTo(() => migration.DataTypes).Returns(dataTypes); //migration.Expect(m => m.Methods).Return(Enumerable.Empty<string>()); MigrationReport report = new MigrationReport(MigrationName, string.Empty, migration); string errors; string warnings; Validate(report, out errors, out warnings); Assert.AreEqual( string.Format(CultureInfo.CurrentCulture, "Migration '{0}' uses the data type '{1}(777)' which is not supported by '{2}'.", MigrationName, DbType.Int32, Platform) + Environment.NewLine + string.Format(CultureInfo.CurrentCulture, "Migration '{0}' uses the data type '{1}(null,777)' which is not supported by '{2}'.", MigrationName, DbType.String, Platform) + Environment.NewLine + string.Format(CultureInfo.CurrentCulture, "Migration '{0}' uses the data type '{1}' which is not supported by '{2}'.", MigrationName, DbType.Decimal, Platform), errors); Assert.That(warnings, Is.Null.Or.Empty); }
public void VerifyValidationError(IDatabase database, string expectedError, string expectedLongestName) { MigrationReport report = MigrationReport.Create((Database)database, string.Empty, A.Fake <IMigrationContext>()); Assert.AreEqual(expectedError, report.Error, "The error is wrong."); Assert.AreEqual(expectedLongestName, report.LongestName, "The longest name is wrong."); }
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()); }
public int Execute() { var projectsToMigrate = GetProjectsToMigrate(_projectArg); var msBuildTemplate = _templateFile != null? ProjectRootElement.TryOpen(_templateFile) : _temporaryDotnetNewProject.MSBuildProject; var sdkVersion = _sdkVersion ?? _temporaryDotnetNewProject.MSBuildProject.GetSdkVersion(); EnsureNotNull(sdkVersion, "Null Sdk Version"); MigrationReport migrationReport = null; foreach (var project in projectsToMigrate) { var projectDirectory = Path.GetDirectoryName(project); var outputDirectory = projectDirectory; var migrationSettings = new MigrationSettings(projectDirectory, outputDirectory, sdkVersion, msBuildTemplate, _xprojFilePath); var projectMigrationReport = new ProjectMigrator().Migrate(migrationSettings, _skipProjectReferences); if (migrationReport == null) { migrationReport = projectMigrationReport; } else { migrationReport = migrationReport.Merge(projectMigrationReport); } } WriteReport(migrationReport); return(migrationReport.FailedProjectsCount); }
private void UpdateSolutionFile(MigrationReport migrationReport) { if (_slnFile == null) { return; } if (migrationReport.FailedProjectsCount > 0) { return; } foreach (var project in _slnFile.Projects) { var projectDirectory = Path.Combine( _slnFile.BaseDirectory, Path.GetDirectoryName(project.FilePath)); var csprojFiles = new DirectoryInfo(projectDirectory) .EnumerateFiles() .Where(f => f.Extension == ".csproj"); if (csprojFiles.Count() == 1) { project.FilePath = Path.Combine(Path.GetDirectoryName(project.FilePath), csprojFiles.First().Name); project.TypeGuid = ProjectTypeGuids.CSharpProjectTypeGuid; } } _slnFile.Write(); }
private void BackupProjects(MigrationReport migrationReport) { foreach (var report in migrationReport.ProjectMigrationReports) { var backupPlan = new MigrationBackupPlan( new DirectoryInfo(report.ProjectDirectory), _workspaceDirectory); backupPlan.PerformBackup(); } }
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 static void AssertAreEqual(IProvider sqlProvider, IProvider smoProvider, Database database) { MigrationReport report = MigrationReport.Create(database, string.Empty); Assert.IsEmpty(report.Error); var sqlTranslator = new CommandsToSqlTranslator(sqlProvider); var smoTranslator = new CommandsToSqlTranslator(smoProvider); var context = MockRepository.GenerateStub <IRuntimeContext>(); ScriptComparer.AssertAreEqual(smoTranslator.TranslateToSql(database, context), sqlTranslator.TranslateToSql(database, context)); }
private void WriteReport(MigrationReport migrationReport) { if (!string.IsNullOrEmpty(_reportFile)) { using (var outputTextWriter = GetReportFileOutputTextWriter()) { outputTextWriter.Write(GetReportContent(migrationReport)); } } WriteReportToStdOut(migrationReport); }
private void UpdateSolutionFile(MigrationReport migrationReport) { if (_slnFile == null) { return; } if (migrationReport.FailedProjectsCount > 0) { return; } List <string> csprojFilesToAdd = new List <string>(); var slnPathWithTrailingSlash = PathUtility.EnsureTrailingSlash(_slnFile.BaseDirectory); foreach (var report in migrationReport.ProjectMigrationReports) { var reportPathWithTrailingSlash = PathUtility.EnsureTrailingSlash(report.ProjectDirectory); var reportRelPath = Path.Combine( PathUtility.GetRelativePath(slnPathWithTrailingSlash, reportPathWithTrailingSlash), report.ProjectName + ".xproj"); var projects = _slnFile.Projects.Where(p => p.FilePath == reportRelPath); var migratedProjectName = report.ProjectName + ".csproj"; if (projects.Count() == 1) { var slnProject = projects.Single(); slnProject.FilePath = Path.Combine( Path.GetDirectoryName(slnProject.FilePath), migratedProjectName); slnProject.TypeGuid = ProjectTypeGuids.CSharpProjectTypeGuid; } else { csprojFilesToAdd.Add(Path.Combine(report.ProjectDirectory, migratedProjectName)); } foreach (var preExisting in report.PreExistingCsprojDependencies) { csprojFilesToAdd.Add(Path.Combine(report.ProjectDirectory, preExisting)); } } _slnFile.Write(); foreach (var csprojFile in csprojFilesToAdd) { AddProject(_slnFile.FullPath, csprojFile); } }
private void MoveProjectJsonArtifactsToBackup(MigrationReport migrationReport) { if (_skipBackup) { return; } if (migrationReport.FailedProjectsCount > 0) { return; } BackupProjects(migrationReport); }
private string GetReportSummary(MigrationReport migrationReport) { StringBuilder sb = new StringBuilder(); sb.AppendLine(LocalizableStrings.MigrationReportSummary); sb.AppendLine( string.Format(LocalizableStrings.MigrationReportTotalProjects, migrationReport.MigratedProjectsCount)); sb.AppendLine(string.Format( LocalizableStrings.MigrationReportSucceededProjects, migrationReport.SucceededProjectsCount)); sb.AppendLine(string.Format( LocalizableStrings.MigrationReportFailedProjects, migrationReport.FailedProjectsCount)); return(sb.ToString()); }
public void VerifyMigrationReportProps(IDatabase database, IEnumerable <DataType> expectedDataTypes, IEnumerable <DataType> expectedPrimaryKeyDataTypes, IEnumerable <DataType> expectedIdentityDataTypes, string expectedLongestName) { const string migrationName = "Test Migration"; MigrationReport report = MigrationReport.Create((Database)database, migrationName, A.Fake <IMigrationContext>()); Assert.AreEqual(migrationName, report.MigrationName); Assert.IsEmpty(report.Error, "These cases should not have any errors."); CollectionAssert.AreEquivalent(expectedDataTypes.ToList(), report.DataTypes.ToList(), "The collection of used data types is wrong."); CollectionAssert.AreEquivalent(expectedPrimaryKeyDataTypes.ToList(), report.PrimaryKeyDataTypes.ToList(), "The collection of used data types for primary keys is wrong."); CollectionAssert.AreEquivalent(expectedIdentityDataTypes.ToList(), report.IdentityDataTypes.ToList(), "The collection of used data types for identity columns is wrong."); Assert.AreEqual(expectedLongestName, report.LongestName, "The longest name is wrong."); }
private void UpdateSolutionFile(MigrationReport migrationReport) { if (_slnFile != null) { UpdateSolutionFile(migrationReport, _slnFile); } else { foreach (var slnPath in _workspaceDirectory.EnumerateFiles("*.sln")) { var slnFile = SlnFile.Read(slnPath.FullName); UpdateSolutionFile(migrationReport, slnFile); } } }
private void BackupProjects(MigrationReport migrationReport) { var projectDirectories = new List<DirectoryInfo>(); foreach (var report in migrationReport.ProjectMigrationReports) { projectDirectories.Add(new DirectoryInfo(report.ProjectDirectory)); } var backupPlan = new MigrationBackupPlan( projectDirectories, _workspaceDirectory); backupPlan.PerformBackup(); Reporter.Output.WriteLine($"Files backed up to {backupPlan.RootBackupDirectory.FullName}"); }
private static string GetWarnings(IEnumerable <ProviderInfo> providerInfos, MigrationOptions options, out string warnings) { var dataTypes = new List <UsedDataType> { new UsedDataType(new DataType(DbType.Guid), false, false), new UsedDataType(new DataType(DbType.String), false, false), }; IRecordedMigration migration = A.Fake <IRecordedMigration>(); A.CallTo(() => migration.DataTypes).Returns(dataTypes); //migration.Expect(m => m.Methods).Return(Enumerable.Empty<string>()); MigrationReport report = new MigrationReport(MigrationName, string.Empty, migration); string errors; Validate(providerInfos, options, report, out errors, out warnings); return(errors); }
private static string GetWarnings(MigrationOptions options, out string warnings) { var dataTypes = new List <UsedDataType> { new UsedDataType(new DataType(DbType.Guid, 0, 0), false, false), new UsedDataType(new DataType(DbType.String, 0, 0), false, false), }; IRecordedMigration migration = MockRepository.GenerateStub <IRecordedMigration>(); migration.Expect(m => m.DataTypes).Return(dataTypes); migration.Expect(m => m.Methods).Return(Enumerable.Empty <string>()); MigrationReport report = new MigrationReport(MigrationName, string.Empty, migration); string errors; Validate(options, report, out errors, out warnings); return(errors); }
public void VerifyUnsupportedMethodsAreReported() { IRecordedMigration migration = MockRepository.GenerateStub <IRecordedMigration>(); migration.Expect(m => m.DataTypes).Return(Enumerable.Empty <UsedDataType>()); migration.Expect(m => m.Methods).Return(new[] { "CreateTable", "DropTable" }); MigrationReport report = new MigrationReport(MigrationName, string.Empty, migration); string errors; string warnings; Validate(report, out errors, out warnings); Assert.AreEqual( string.Format(CultureInfo.CurrentCulture, "Migration '{0}' calls the '{1}' method which is not supported by '{2}': DropTable is not supported because this is just a test.", MigrationName, "DropTable", ProviderName), errors); Assert.IsNullOrEmpty(warnings); }
public void VerifyUnsupportedMethodsAreReported() { IRecordedMigration migration = A.Fake <IRecordedMigration>(); //migration.Expect(m => m.DataTypes).Return(Enumerable.Empty<UsedDataType>()); A.CallTo(() => migration.Methods).Returns(new[] { "CreateTable", "AddColumn" }); MigrationReport report = new MigrationReport(MigrationName, string.Empty, migration); string errors; string warnings; Validate(report, out errors, out warnings); Assert.AreEqual( string.Format(CultureInfo.CurrentCulture, "Migration '{0}' calls the '{1}' method which is not supported by '{2}': AddColumn is not supported because this is just a test.", MigrationName, "AddColumn", Platform), errors); Assert.That(warnings, Is.Null.Or.Empty); }
public int Execute() { var temporaryDotnetNewProject = new TemporaryDotnetNewTemplateProject(); var projectsToMigrate = GetProjectsToMigrate(_projectArg); var msBuildTemplatePath = _templateFile ?? temporaryDotnetNewProject.MSBuildProjectPath; var sdkVersion = _sdkVersion ?? temporaryDotnetNewProject.MSBuildProject.GetSdkVersion(); EnsureNotNull(sdkVersion, "Null Sdk Version"); MigrationReport migrationReport = null; foreach (var project in projectsToMigrate) { var projectDirectory = Path.GetDirectoryName(project); var outputDirectory = projectDirectory; var migrationSettings = new MigrationSettings( projectDirectory, outputDirectory, sdkVersion, msBuildTemplatePath, _xprojFilePath); var projectMigrationReport = new ProjectMigrator().Migrate(migrationSettings, _skipProjectReferences); if (migrationReport == null) { migrationReport = projectMigrationReport; } else { migrationReport = migrationReport.Merge(projectMigrationReport); } } WriteReport(migrationReport); temporaryDotnetNewProject.Clean(); MoveProjectJsonArtifactsToBackup(migrationReport); return(migrationReport.FailedProjectsCount); }
private void BackupProjects(MigrationReport migrationReport) { var projectDirectories = new List <DirectoryInfo>(); foreach (var report in migrationReport.ProjectMigrationReports) { projectDirectories.Add(new DirectoryInfo(report.ProjectDirectory)); } var backupPlan = new MigrationBackupPlan( projectDirectories, _workspaceDirectory); backupPlan.PerformBackup(); Reporter.Output.WriteLine(string.Format( LocalizableStrings.MigrateFilesBackupLocation, backupPlan.RootBackupDirectory.FullName)); }
public int Execute() { var temporaryDotnetNewProject = new TemporaryDotnetNewTemplateProject(_dotnetCoreTemplateCreator); var projectsToMigrate = GetProjectsToMigrate(_projectArg); var msBuildTemplatePath = _templateFile ?? temporaryDotnetNewProject.MSBuildProjectPath; MigrationReport migrationReport = null; foreach (var project in projectsToMigrate) { var projectDirectory = Path.GetDirectoryName(project); var outputDirectory = projectDirectory; var migrationSettings = new MigrationSettings( projectDirectory, outputDirectory, msBuildTemplatePath, _xprojFilePath, null, _slnFile); var projectMigrationReport = new ProjectMigrator().Migrate(migrationSettings, _skipProjectReferences); if (migrationReport == null) { migrationReport = projectMigrationReport; } else { migrationReport = migrationReport.Merge(projectMigrationReport); } } WriteReport(migrationReport); temporaryDotnetNewProject.Clean(); UpdateSolutionFile(migrationReport); MoveProjectJsonArtifactsToBackup(migrationReport); return(migrationReport.FailedProjectsCount); }
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)); }
public void VerifyViolatingMaximumDbObjectNameLengthIsReported() { const string longestName = "Some very long name"; IRecordedMigration migration = A.Fake <IRecordedMigration>(); A.CallTo(() => migration.NewObjectNames).Returns(new[] { longestName, longestName.Substring(1) }); //A.CallTo(() => migration.DataTypes).Returns(Enumerable.Empty<UsedDataType>()); //migration.Expect(m => m.Methods).Return(Enumerable.Empty<string>()); var report = new MigrationReport(MigrationName, "Some other validation error.", migration); string errors; string warnings; Validate(report, out errors, out warnings); Assert.AreEqual( string.Format(CultureInfo.CurrentCulture, "Error in migration '{0}': Some other validation error.", MigrationName) + Environment.NewLine + string.Format(CultureInfo.CurrentCulture, "Migration '{0}' contains object names that are longer than what is supported by '{1}' ('{2}': {3}, supported: {4}).", MigrationName, Platform, longestName, longestName.Length, MaximumSupportedLength), errors); Assert.That(warnings, Is.Null.Or.Empty); }
public void VerifyWarningsForOdbc() { var dataTypes = new List <UsedDataType> { new UsedDataType(new DataType(DbType.Int64), false, false), }; IRecordedMigration migration = A.Fake <IRecordedMigration>(); A.CallTo(() => migration.DataTypes).Returns(dataTypes); //migration.Expect(m => m.Methods).Return(Enumerable.Empty<string>()); MigrationReport report = new MigrationReport(MigrationName, string.Empty, migration); string errors; string warnings; Validate(report, out errors, out warnings); Assert.That(errors, Is.Null.Or.Empty); Assert.AreEqual( string.Format(CultureInfo.CurrentCulture, "Migration '{0}' uses the data type '{1}' which is not fully supported by '{2}': Int64 is not supported for DbParameters with ODBC; requires calling ToString to directly inline the value in the CommandText.", MigrationName, DbType.Int64, Platform), warnings); }
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); var warningContent = GetProjectReportWarningContent(projectMigrationReport, colored: true); _reporterWriteLine(warningContent); if (!string.IsNullOrEmpty(errorContent)) { Reporter.Error.WriteLine(errorContent); } else { _reporterWriteLine(successContent); } } _reporterWriteLine(GetReportSummary(migrationReport)); _reporterWriteLine(LocalizableStrings.MigrationAdditionalHelp); }
public void ProcessNodesInWorkspace( XmlDocument xmlDoc, Version workspaceVersion, Version currentVersion, NodeFactory nodeFactory) { if (DynamoModel.EnableMigrationLogging) { // For each new file opened, create a new migration report migrationReport = new MigrationReport(); } XmlNodeList elNodes = xmlDoc.GetElementsByTagName("Elements"); if (elNodes.Count == 0) elNodes = xmlDoc.GetElementsByTagName("dynElements"); // A new list to store migrated nodes. var migratedNodes = new List<XmlElement>(); XmlNode elNodesList = elNodes[0]; foreach (XmlElement elNode in elNodesList.ChildNodes) { string typeName = elNode.Attributes["type"].Value; typeName = Nodes.Utilities.PreprocessTypeName(typeName); Type type; if (!nodeFactory.ResolveType(typeName, out type) && !nodeMigrationLookup.TryGetValue(typeName, out type)) { // If we are not able to resolve the type given its name, // turn it into a deprecated node so that user is aware. migratedNodes.Add(CreateMissingNode(elNode, 1, 1)); continue; // Error displayed in console, continue on. } // Migrate the given node into one or more new nodes. var migrationData = MigrateXmlNode(currentVersion, elNode, type, workspaceVersion); migratedNodes.AddRange(migrationData.MigratedNodes); } if (DynamoModel.EnableMigrationLogging) { string dynFilePath = xmlDoc.BaseURI; migrationReport.WriteToXmlFile(dynFilePath); } // Replace the old child nodes with the migrated nodes. Note that // "RemoveAll" also remove all attributes, but since we don't have // any attribute here, it is safe. Added an assertion to make sure // we revisit this codes if we do add attributes to 'elNodesList'. // Debug.Assert(elNodesList.Attributes.Count == 0); elNodesList.RemoveAll(); foreach (XmlElement migratedNode in migratedNodes) elNodesList.AppendChild(migratedNode); }
private void UpdateSolutionFile(MigrationReport migrationReport) { if (_slnFile == null) { return; } if (migrationReport.FailedProjectsCount > 0) { return; } var csprojFilesToAdd = new HashSet<string>(); var slnPathWithTrailingSlash = PathUtility.EnsureTrailingSlash(_slnFile.BaseDirectory); foreach (var report in migrationReport.ProjectMigrationReports) { var reportPathWithTrailingSlash = PathUtility.EnsureTrailingSlash(report.ProjectDirectory); var relativeReportPath = PathUtility.GetRelativePath( slnPathWithTrailingSlash, reportPathWithTrailingSlash); var xprojPath = Path.Combine(relativeReportPath, report.ProjectName + ".xproj"); var xprojProjectsReferencedBySolution = _slnFile.Projects.Where(p => p.FilePath == xprojPath); var migratedProjectName = report.ProjectName + ".csproj"; if (xprojProjectsReferencedBySolution.Count() == 1) { var slnProject = xprojProjectsReferencedBySolution.Single(); slnProject.FilePath = Path.Combine( Path.GetDirectoryName(slnProject.FilePath), migratedProjectName); slnProject.TypeGuid = ProjectTypeGuids.CSharpProjectTypeGuid; } else { var csprojPath = Path.Combine(relativeReportPath, migratedProjectName); var solutionContainsCsprojPriorToMigration = _slnFile.Projects .Where(p => p.FilePath == csprojPath) .Any(); if (!solutionContainsCsprojPriorToMigration) { csprojFilesToAdd.Add(Path.Combine(report.ProjectDirectory, migratedProjectName)); } } foreach (var preExisting in report.PreExistingCsprojDependencies) { csprojFilesToAdd.Add(Path.Combine(report.ProjectDirectory, preExisting)); } } Version version; if (!Version.TryParse(_slnFile.VisualStudioVersion, out version) || version.Major < 15) { _slnFile.ProductDescription = ProductDescription; _slnFile.VisualStudioVersion = VisualStudioVersion; _slnFile.MinimumVisualStudioVersion = MinimumVisualStudioVersion; } _slnFile.Write(); foreach (var csprojFile in csprojFilesToAdd) { AddProject(_slnFile.FullPath, csprojFile); } }