Skip to content

Commit 450493b

Browse files
authored
Merge branch 'release/10.0.2xx' into merge/release/10.0.1xx-to-release/10.0.2xx
2 parents 0739b5a + 71017c2 commit 450493b

25 files changed

+238
-563
lines changed

src/Cli/Microsoft.DotNet.FileBasedPrograms/Microsoft.DotNet.FileBasedPrograms.Package.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212

1313
<!-- NuGet -->
1414
<IsPackable>true</IsPackable>
15+
<IsShipping>true</IsShipping>
1516
<IsSourcePackage>true</IsSourcePackage>
1617
<PackageId>Microsoft.DotNet.FileBasedPrograms</PackageId>
1718
<IncludeBuildOutput>false</IncludeBuildOutput>

src/Cli/dotnet/Commands/CliCommandStrings.resx

Lines changed: 6 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -378,12 +378,6 @@ For MSTest before 2.2.4, the timeout is used for all testcases.</value>
378378
<data name="CmdDGFileIOException" xml:space="preserve">
379379
<value>Unable to generate a temporary file for project '{0}'. Cannot add package reference. Clear the temp directory and try again.</value>
380380
</data>
381-
<data name="CmdDirectoryDescription" xml:space="preserve">
382-
<value>Defines the path of directory to run. If not specified, it defaults to the current directory.</value>
383-
</data>
384-
<data name="CmdDirectoryPathName" xml:space="preserve">
385-
<value>DIRECTORY_PATH</value>
386-
</data>
387381
<data name="CmdDisableParallelOptionDescription" xml:space="preserve">
388382
<value>Prevent restoring multiple projects in parallel.</value>
389383
</data>
@@ -550,11 +544,13 @@ This is equivalent to deleting project.assets.json.</value>
550544
<value>Consider packages with prerelease versions when searching for newer packages. Requires the '--outdated' option.</value>
551545
</data>
552546
<data name="CmdProjectDescriptionFormat" xml:space="preserve">
553-
<value>Defines the path of the project file to {0}. Use path to the project file, or path to the directory containing the project file. If not specified, it defaults to the current directory.</value>
554-
<comment>{0} is the verb (e.g., "test", "run")</comment>
547+
<value>Defines the path of the project file to run. Use path to the project file, or path to the directory containing the project file. If not specified, it defaults to the current directory.</value>
555548
</data>
556-
<data name="CmdProjectPathName" xml:space="preserve">
557-
<value>PROJECT_PATH</value>
549+
<data name="CmdProjectOrSolutionDescriptionFormat" xml:space="preserve">
550+
<value>Defines the path of the project or solution file to test. Use path to the project file, or path to the directory containing the project file. If not specified, it defaults to the current directory.</value>
551+
</data>
552+
<data name="CmdProjectOrSolutionPathName" xml:space="preserve">
553+
<value>PROJECT_OR_SOLUTION_PATH</value>
558554
</data>
559555
<data name="CmdReevaluateOptionDescription" xml:space="preserve">
560556
<value>Forces restore to reevaluate all dependencies even if a lock file already exists.</value>
@@ -600,12 +596,6 @@ If not specified the file will be generated inside the default 'TestResults' dir
600596
<data name="CmdSolutionPathName" xml:space="preserve">
601597
<value>SOLUTION_PATH</value>
602598
</data>
603-
<data name="VerbRun" xml:space="preserve">
604-
<value>run</value>
605-
</data>
606-
<data name="VerbTest" xml:space="preserve">
607-
<value>test</value>
608-
</data>
609599
<data name="CmdSourceOption" xml:space="preserve">
610600
<value>SOURCE</value>
611601
</data>
@@ -2617,9 +2607,6 @@ Proceed?</value>
26172607
<data name="DotnetTestPipeOverlapping" xml:space="preserve">
26182608
<value>'dotnet' unexpectedly received overlapping messages from the 'dotnet test' named pipe.</value>
26192609
</data>
2620-
<data name="DotnetTestPipeIncompleteSize" xml:space="preserve">
2621-
<value>'dotnet' unexpectedly received less than 4 bytes from the 'dotnet test' named pipe.</value>
2622-
</data>
26232610
<data name="InternalLoopAsyncDidNotExitSuccessfullyErrorMessage" xml:space="preserve">
26242611
<value>Method '{0}' did not exit successfully</value>
26252612
</data>

src/Cli/dotnet/Commands/Run/RunCommandParser.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ internal static class RunCommandParser
1919

2020
public static readonly Option<string> ProjectOption = new("--project")
2121
{
22-
Description = string.Format(CliCommandStrings.CmdProjectDescriptionFormat, CliCommandStrings.VerbRun),
22+
Description = CliCommandStrings.CmdProjectDescriptionFormat,
2323
HelpName = CliCommandStrings.CommandOptionProjectHelpName
2424
};
2525

src/Cli/dotnet/Commands/Test/MTP/MSBuildHandler.cs

Lines changed: 7 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -16,88 +16,24 @@ internal sealed class MSBuildHandler(BuildOptions buildOptions)
1616

1717
public bool RunMSBuild()
1818
{
19-
if (!ValidationUtility.ValidateBuildPathOptions(_buildOptions))
20-
{
21-
return false;
22-
}
23-
24-
int msBuildExitCode;
25-
string path;
2619
PathOptions pathOptions = _buildOptions.PathOptions;
2720

28-
if (!string.IsNullOrEmpty(pathOptions.ProjectPath))
29-
{
30-
path = PathUtility.GetFullPath(pathOptions.ProjectPath);
31-
32-
msBuildExitCode = Directory.Exists(path)
33-
? RunBuild(path, expectProject: true)
34-
: RunBuild(path, isSolution: false);
35-
}
36-
else if (!string.IsNullOrEmpty(pathOptions.SolutionPath))
37-
{
38-
path = PathUtility.GetFullPath(pathOptions.SolutionPath);
39-
40-
msBuildExitCode = Directory.Exists(path)
41-
? RunBuild(path, expectSolution: true)
42-
: RunBuild(path, isSolution: true);
43-
}
44-
else
21+
if (!ValidationUtility.ValidateBuildPathOptions(pathOptions, out string? projectOrSolutionFilePath, out bool isSolution))
4522
{
46-
path = PathUtility.GetFullPath(Directory.GetCurrentDirectory());
47-
msBuildExitCode = RunBuild(path);
48-
}
49-
50-
if (msBuildExitCode != ExitCode.Success)
51-
{
52-
Reporter.Error.WriteLine(string.Format(CliCommandStrings.CmdMSBuildProjectsPropertiesErrorDescription, msBuildExitCode));
5323
return false;
5424
}
5525

56-
return true;
57-
}
58-
59-
private int RunBuild(string directoryPath, bool expectProject = false, bool expectSolution = false)
60-
{
61-
bool solutionOrProjectFileFound;
62-
string message;
63-
string projectOrSolutionFilePath;
64-
bool isSolution;
65-
66-
if (expectProject)
67-
{
68-
(solutionOrProjectFileFound, message) = SolutionAndProjectUtility.TryGetProjectFilePath(directoryPath, out projectOrSolutionFilePath);
69-
isSolution = false;
70-
}
71-
else if (expectSolution)
72-
{
73-
(solutionOrProjectFileFound, message) = SolutionAndProjectUtility.TryGetSolutionFilePath(directoryPath, out projectOrSolutionFilePath);
74-
isSolution = true;
75-
}
76-
else
77-
{
78-
(solutionOrProjectFileFound, message) = SolutionAndProjectUtility.TryGetProjectOrSolutionFilePath(directoryPath, out projectOrSolutionFilePath, out isSolution);
79-
}
80-
81-
if (!solutionOrProjectFileFound)
82-
{
83-
Reporter.Error.WriteLine(message);
84-
return ExitCode.GenericFailure;
85-
}
86-
8726
(IEnumerable<ParallelizableTestModuleGroupWithSequentialInnerModules> projects, bool restored) = GetProjectsProperties(projectOrSolutionFilePath, isSolution);
8827

8928
InitializeTestApplications(projects);
9029

91-
return restored && !_testApplications.IsEmpty ? ExitCode.Success : ExitCode.GenericFailure;
92-
}
93-
94-
private int RunBuild(string filePath, bool isSolution)
95-
{
96-
(IEnumerable<ParallelizableTestModuleGroupWithSequentialInnerModules> projects, bool restored) = GetProjectsProperties(filePath, isSolution);
97-
98-
InitializeTestApplications(projects);
30+
if (!restored || _testApplications.IsEmpty)
31+
{
32+
Reporter.Error.WriteLine(string.Format(CliCommandStrings.CmdMSBuildProjectsPropertiesErrorDescription, ExitCode.GenericFailure));
33+
return false;
34+
}
9935

100-
return restored && !_testApplications.IsEmpty ? ExitCode.Success : ExitCode.GenericFailure;
36+
return true;
10137
}
10238

10339
private void InitializeTestApplications(IEnumerable<ParallelizableTestModuleGroupWithSequentialInnerModules> moduleGroups)

src/Cli/dotnet/Commands/Test/MTP/MSBuildUtility.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ public static BuildOptions GetBuildOptions(ParseResult parseResult)
9393
}
9494

9595
PathOptions pathOptions = new(
96-
parseResult.GetValue(MicrosoftTestingPlatformOptions.ProjectOption),
96+
parseResult.GetValue(MicrosoftTestingPlatformOptions.ProjectOrSolutionOption),
9797
parseResult.GetValue(MicrosoftTestingPlatformOptions.SolutionOption),
9898
resultsDirectory,
9999
configFile,

src/Cli/dotnet/Commands/Test/MTP/MicrosoftTestingPlatformOptions.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,10 @@ namespace Microsoft.DotNet.Cli.Commands.Test;
77

88
internal static class MicrosoftTestingPlatformOptions
99
{
10-
public static readonly Option<string> ProjectOption = new("--project")
10+
public static readonly Option<string> ProjectOrSolutionOption = new("--project")
1111
{
12-
Description = string.Format(CliCommandStrings.CmdProjectDescriptionFormat, CliCommandStrings.VerbTest),
13-
HelpName = CliCommandStrings.CmdProjectPathName,
12+
Description = CliCommandStrings.CmdProjectOrSolutionDescriptionFormat,
13+
HelpName = CliCommandStrings.CmdProjectOrSolutionPathName,
1414
Arity = ArgumentArity.ExactlyOne
1515
};
1616

src/Cli/dotnet/Commands/Test/MTP/Options.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ namespace Microsoft.DotNet.Cli.Commands.Test;
55

66
internal record TestOptions(bool IsHelp, bool IsDiscovery, IReadOnlyDictionary<string, string> EnvironmentVariables);
77

8-
internal record PathOptions(string? ProjectPath, string? SolutionPath, string? ResultsDirectoryPath, string? ConfigFilePath, string? DiagnosticOutputDirectoryPath);
8+
internal record PathOptions(string? ProjectOrSolutionPath, string? SolutionPath, string? ResultsDirectoryPath, string? ConfigFilePath, string? DiagnosticOutputDirectoryPath);
99

1010
internal record BuildOptions(
1111
PathOptions PathOptions,

src/Cli/dotnet/Commands/Test/MTP/SolutionAndProjectUtility.cs

Lines changed: 0 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -115,31 +115,6 @@ public static (bool SolutionOrProjectFileFound, string Message) TryGetProjectOrS
115115
return (true, string.Empty);
116116
}
117117

118-
public static (bool ProjectFileFound, string Message) TryGetProjectFilePath(string directory, out string projectFilePath)
119-
{
120-
projectFilePath = string.Empty;
121-
122-
if (!Directory.Exists(directory))
123-
{
124-
return (false, string.Format(CliCommandStrings.CmdNonExistentDirectoryErrorDescription, directory));
125-
}
126-
127-
var actualProjectFiles = GetProjectFilePaths(directory);
128-
129-
if (actualProjectFiles.Length == 0)
130-
{
131-
return (false, string.Format(CliStrings.CouldNotFindAnyProjectInDirectory, directory));
132-
}
133-
134-
if (actualProjectFiles.Length == 1)
135-
{
136-
projectFilePath = actualProjectFiles[0];
137-
return (true, string.Empty);
138-
}
139-
140-
return (false, string.Format(CliStrings.MoreThanOneProjectInDirectory, directory));
141-
}
142-
143118
public static (bool SolutionFileFound, string Message) TryGetSolutionFilePath(string directory, out string solutionFilePath)
144119
{
145120
solutionFilePath = string.Empty;

src/Cli/dotnet/Commands/Test/MTP/ValidationUtility.cs

Lines changed: 55 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
// The .NET Foundation licenses this file to you under the MIT license.
33

44
using System.CommandLine;
5+
using System.Diagnostics.CodeAnalysis;
56
using Microsoft.DotNet.Cli.Extensions;
67
using Microsoft.DotNet.Cli.Utils;
78

@@ -23,7 +24,7 @@ static void ValidatePathOptions(ParseResult parseResult)
2324
if (parseResult.HasOption(MicrosoftTestingPlatformOptions.SolutionOption))
2425
count++;
2526

26-
if (parseResult.HasOption(MicrosoftTestingPlatformOptions.ProjectOption))
27+
if (parseResult.HasOption(MicrosoftTestingPlatformOptions.ProjectOrSolutionOption))
2728
count++;
2829

2930
if (count > 1)
@@ -48,18 +49,46 @@ static void ValidateOptionsIrrelevantToModulesFilter(ParseResult parseResult)
4849
}
4950
}
5051

51-
public static bool ValidateBuildPathOptions(BuildOptions buildPathOptions)
52+
public static bool ValidateBuildPathOptions(PathOptions pathOptions, [NotNullWhen(true)] out string? projectOrSolutionFilePath, out bool isSolution)
5253
{
53-
PathOptions pathOptions = buildPathOptions.PathOptions;
54-
55-
if (!string.IsNullOrEmpty(pathOptions.ProjectPath))
54+
if (!string.IsNullOrEmpty(pathOptions.ProjectOrSolutionPath))
5655
{
57-
return ValidateProjectPath(pathOptions.ProjectPath);
56+
return ValidateProjectOrSolutionPath(pathOptions.ProjectOrSolutionPath, out projectOrSolutionFilePath, out isSolution);
5857
}
5958

6059
if (!string.IsNullOrEmpty(pathOptions.SolutionPath))
6160
{
62-
return ValidateSolutionPath(pathOptions.SolutionPath);
61+
isSolution = true;
62+
return ValidateSolutionPath(pathOptions.SolutionPath, out projectOrSolutionFilePath);
63+
}
64+
65+
return TryGetProjectOrSolutionFromDirectory(Directory.GetCurrentDirectory(), onlyConsiderSolutions: false, out projectOrSolutionFilePath, out isSolution);
66+
}
67+
68+
private static bool TryGetProjectOrSolutionFromDirectory(
69+
string directory,
70+
bool onlyConsiderSolutions,
71+
[NotNullWhen(true)] out string? projectOrSolutionFilePath,
72+
out bool isSolution)
73+
{
74+
bool foundSolutionOrProjectInDirectory;
75+
string? message;
76+
if (onlyConsiderSolutions)
77+
{
78+
isSolution = true;
79+
(foundSolutionOrProjectInDirectory, message) = SolutionAndProjectUtility.TryGetSolutionFilePath(directory, out projectOrSolutionFilePath);
80+
}
81+
else
82+
{
83+
(foundSolutionOrProjectInDirectory, message) = SolutionAndProjectUtility.TryGetProjectOrSolutionFilePath(directory, out projectOrSolutionFilePath, out isSolution);
84+
}
85+
86+
if (!foundSolutionOrProjectInDirectory)
87+
{
88+
Reporter.Error.WriteLine(message);
89+
projectOrSolutionFilePath = null;
90+
isSolution = false;
91+
return false;
6392
}
6493

6594
return true;
@@ -106,40 +135,47 @@ public static void ValidateSolutionOrProjectOrDirectoryOrModulesArePassedCorrect
106135
}
107136
}
108137

109-
private static bool ValidateSolutionPath(string path)
138+
private static bool ValidateSolutionPath(string solutionFileOrDirectory, [NotNullWhen(true)] out string? solutionFile)
110139
{
111140
// If it's a directory, just check if it exists
112-
if (Directory.Exists(path))
141+
if (Directory.Exists(solutionFileOrDirectory))
113142
{
114-
return true;
143+
return TryGetProjectOrSolutionFromDirectory(solutionFileOrDirectory, onlyConsiderSolutions: true, out solutionFile, out _);
115144
}
116145

146+
solutionFile = solutionFileOrDirectory;
147+
117148
// If it's not a directory, validate as a file path
118-
if (!CliConstants.SolutionExtensions.Contains(Path.GetExtension(path)))
149+
if (!CliConstants.SolutionExtensions.Contains(Path.GetExtension(solutionFileOrDirectory)))
119150
{
120-
Reporter.Error.WriteLine(string.Format(CliCommandStrings.CmdInvalidSolutionFileExtensionErrorDescription, path));
151+
Reporter.Error.WriteLine(string.Format(CliCommandStrings.CmdInvalidSolutionFileExtensionErrorDescription, solutionFileOrDirectory));
121152
return false;
122153
}
123154

124-
return ValidateFilePathExists(path);
155+
return ValidateFilePathExists(solutionFile);
125156
}
126157

127-
private static bool ValidateProjectPath(string path)
158+
private static bool ValidateProjectOrSolutionPath(string projectOrSolutionFileOrDirectory, [NotNullWhen(true)] out string? projectOrSolutionFile, out bool isSolution)
128159
{
129160
// If it's a directory, just check if it exists
130-
if (Directory.Exists(path))
161+
if (Directory.Exists(projectOrSolutionFileOrDirectory))
131162
{
132-
return true;
163+
return TryGetProjectOrSolutionFromDirectory(projectOrSolutionFileOrDirectory, onlyConsiderSolutions: false, out projectOrSolutionFile, out isSolution);
133164
}
134165

166+
var extension = Path.GetExtension(projectOrSolutionFileOrDirectory);
167+
isSolution = CliConstants.SolutionExtensions.Contains(extension);
168+
projectOrSolutionFile = projectOrSolutionFileOrDirectory;
135169
// If it's not a directory, validate as a file path
136-
if (!Path.GetExtension(path).EndsWith("proj", StringComparison.OrdinalIgnoreCase))
170+
if (!isSolution && !extension.EndsWith("proj", StringComparison.OrdinalIgnoreCase))
137171
{
138-
Reporter.Error.WriteLine(string.Format(CliCommandStrings.CmdInvalidProjectFileExtensionErrorDescription, path));
172+
projectOrSolutionFile = null;
173+
isSolution = false;
174+
Reporter.Error.WriteLine(string.Format(CliCommandStrings.CmdInvalidProjectFileExtensionErrorDescription, projectOrSolutionFileOrDirectory));
139175
return false;
140176
}
141177

142-
return ValidateFilePathExists(path);
178+
return ValidateFilePathExists(projectOrSolutionFileOrDirectory);
143179
}
144180

145181
private static bool ValidateFilePathExists(string filePath)

src/Cli/dotnet/Commands/Test/TestCommandParser.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -235,7 +235,7 @@ private static Command GetTestingPlatformCliCommand()
235235
{
236236
var command = new MicrosoftTestingPlatformTestCommand("test", CliCommandStrings.DotnetTestCommandMTPDescription);
237237
command.SetAction(parseResult => command.Run(parseResult));
238-
command.Options.Add(MicrosoftTestingPlatformOptions.ProjectOption);
238+
command.Options.Add(MicrosoftTestingPlatformOptions.ProjectOrSolutionOption);
239239
command.Options.Add(MicrosoftTestingPlatformOptions.SolutionOption);
240240
command.Options.Add(MicrosoftTestingPlatformOptions.TestModulesFilterOption);
241241
command.Options.Add(MicrosoftTestingPlatformOptions.TestModulesRootDirectoryOption);

0 commit comments

Comments
 (0)