diff --git a/src/dotnet/commands/dotnet-migrate/MigrateCommand.cs b/src/dotnet/commands/dotnet-migrate/MigrateCommand.cs index 900cb6567..cc5086ab2 100644 --- a/src/dotnet/commands/dotnet-migrate/MigrateCommand.cs +++ b/src/dotnet/commands/dotnet-migrate/MigrateCommand.cs @@ -195,21 +195,24 @@ namespace Microsoft.DotNet.Tools.Migrate else if (projectArg.EndsWith(GlobalSettings.FileName, StringComparison.OrdinalIgnoreCase)) { projects = GetProjectsFromGlobalJson(projectArg); + if (!projects.Any()) + { + throw new Exception("Unable to find any projects in global.json"); + } } else if (Directory.Exists(projectArg)) { projects = Directory.EnumerateFiles(projectArg, Project.FileName, SearchOption.AllDirectories); + if (!projects.Any()) + { + throw new Exception($"No project.json file found in '{projectArg}'"); + } } else { throw new Exception($"Invalid project argument - '{projectArg}' is not a project.json or a global.json file and a directory named '{projectArg}' doesn't exist."); } - - if (!projects.Any()) - { - throw new Exception($"Invalid project argument - Unable to find any projects in global.json or directory '{projectArg}'"); - } - + foreach(var project in projects) { yield return GetProjectJsonPath(project); diff --git a/src/dotnet/commands/dotnet-migrate/Program.cs b/src/dotnet/commands/dotnet-migrate/Program.cs index a60660ab8..9e5b6b84b 100644 --- a/src/dotnet/commands/dotnet-migrate/Program.cs +++ b/src/dotnet/commands/dotnet-migrate/Program.cs @@ -69,6 +69,7 @@ namespace Microsoft.DotNet.Tools.Migrate #else Reporter.Error.WriteLine(ex.Message); #endif + Reporter.Error.WriteLine("Migration failed."); return 1; } } diff --git a/test/dotnet-migrate.Tests/GivenThatIWantToMigrateTestApps.cs b/test/dotnet-migrate.Tests/GivenThatIWantToMigrateTestApps.cs index 0d0ff8cdd..f70322703 100644 --- a/test/dotnet-migrate.Tests/GivenThatIWantToMigrateTestApps.cs +++ b/test/dotnet-migrate.Tests/GivenThatIWantToMigrateTestApps.cs @@ -268,8 +268,54 @@ namespace Microsoft.DotNet.Migration.Tests outputsIdentical.Should().BeTrue(); VerifyAllMSBuildOutputsRunnable(projectDirectory); } + + [Theory] + // https://github.com/dotnet/cli/issues/4313 + [InlineData(true)] + [InlineData(false)] + public void Migration_outputs_error_when_no_projects_found(bool useGlobalJson) + { + var projectDirectory = TestAssetsManager.CreateTestDirectory("Migration_outputs_error_when_no_projects_found"); - private void VerifyMigration(IEnumerable expectedProjects, string rootDir) + string argstr = string.Empty; + string errorMessage = string.Empty; + + if (useGlobalJson) + { + var globalJsonPath = Path.Combine(projectDirectory.Path, "global.json"); + using (FileStream fs = File.Create(globalJsonPath)) + { + using (StreamWriter sw = new StreamWriter(fs)) + { + sw.WriteLine("{"); + sw.WriteLine("\"projects\": [ \".\" ]"); + sw.WriteLine("}"); + } + } + + argstr = globalJsonPath; + errorMessage = "Unable to find any projects in global.json"; + } + else + { + argstr = projectDirectory.Path; + errorMessage = $"No project.json file found in '{projectDirectory.Path}'"; + } + + var result = new TestCommand("dotnet") + .WithWorkingDirectory(projectDirectory.Path) + .ExecuteWithCapturedOutput($"migrate {argstr}"); + + // Expecting an error exit code. + result.ExitCode.Should().Be(1); + + // Verify the error messages. Note that debug builds also show the call stack, so we search + // for the error strings that should be present (rather than an exact match). + result.StdErr.Should().Contain(errorMessage); + result.StdErr.Should().Contain("Migration failed."); + } + + private void VerifyMigration(IEnumerable expectedProjects, string rootDir) { var migratedProjects = Directory.EnumerateFiles(rootDir, "project.json", SearchOption.AllDirectories) .Where(s => Directory.EnumerateFiles(Path.GetDirectoryName(s), "*.csproj").Count() == 1)