diff --git a/src/Cli/Microsoft.DotNet.Cli.Utils/MSBuildPropertyParser.cs b/src/Cli/Microsoft.DotNet.Cli.Utils/MSBuildPropertyParser.cs
index 399ceaecafd1..451560f95415 100644
--- a/src/Cli/Microsoft.DotNet.Cli.Utils/MSBuildPropertyParser.cs
+++ b/src/Cli/Microsoft.DotNet.Cli.Utils/MSBuildPropertyParser.cs
@@ -10,6 +10,10 @@
namespace Microsoft.DotNet.Cli.Utils;
+///
+/// Parses property key value pairs that have already been forwarded through the PropertiesOption class.
+/// Does not parse -p and etc. formats, (this is done by PropertiesOption) but does parse property values separated by =, ;, and using quotes.
+///
public static class MSBuildPropertyParser {
public static IEnumerable<(string key, string value)> ParseProperties(string input) {
var currentPos = 0;
diff --git a/src/Cli/dotnet/ReleasePropertyProjectLocator.cs b/src/Cli/dotnet/ReleasePropertyProjectLocator.cs
index 52aac61ab583..e16b2b3c7890 100644
--- a/src/Cli/dotnet/ReleasePropertyProjectLocator.cs
+++ b/src/Cli/dotnet/ReleasePropertyProjectLocator.cs
@@ -188,13 +188,15 @@ private bool IsValidProjectFilePath(string path)
private Dictionary GetGlobalPropertiesFromUserArgs(ParseResult parseResult)
{
Dictionary globalProperties = new Dictionary(StringComparer.OrdinalIgnoreCase);
-
string[] globalPropEnumerable = parseResult.GetValueForOption(CommonOptions.PropertiesOption);
- foreach (var keyEqVal in globalPropEnumerable)
+ foreach (var keyEqValString in globalPropEnumerable)
{
- string[] keyValuePair = keyEqVal.Split("=", 2);
- globalProperties[keyValuePair[0]] = keyValuePair[1];
+ var propertyPairs = MSBuildPropertyParser.ParseProperties(keyEqValString);
+ foreach (var propertyKeyValue in propertyPairs)
+ {
+ globalProperties[propertyKeyValue.key] = propertyKeyValue.value;
+ }
}
return globalProperties;
}
diff --git a/src/Tests/Microsoft.NET.Publish.Tests/GivenThatWeWantToPublishAHelloWorldProject.cs b/src/Tests/Microsoft.NET.Publish.Tests/GivenThatWeWantToPublishAHelloWorldProject.cs
index 978dc4677f8a..4637a9158f6b 100644
--- a/src/Tests/Microsoft.NET.Publish.Tests/GivenThatWeWantToPublishAHelloWorldProject.cs
+++ b/src/Tests/Microsoft.NET.Publish.Tests/GivenThatWeWantToPublishAHelloWorldProject.cs
@@ -4,6 +4,7 @@
using System;
using System.IO;
using System.Linq;
+using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Security.Cryptography;
@@ -688,11 +689,13 @@ public void PublishRelease_does_not_override_custom_Configuration_on_proj_and_lo
[InlineData("-property:Configuration=Debug")]
[InlineData("--property:Configuration=Debug")]
[InlineData("/p:Configuration=Debug")]
+ [InlineData("-p:_IsPublishing=true;Configuration=Debug")]
+ [InlineData("-p:_IsPublishing=true;Configuration=Debug;")]
[InlineData("/property:Configuration=Debug")]
public void PublishRelease_does_not_override_Configuration_property_across_formats(string configOpt)
{
var helloWorldAsset = _testAssetsManager
- .CopyTestAsset("HelloWorld", $"PublishReleaseHelloWorldCsProjConfigPropOverride{configOpt}")
+ .CopyTestAsset("HelloWorld", identifier: configOpt)
.WithSource()
.WithTargetFramework(ToolsetInfo.CurrentTargetFramework)
.WithProjectChanges(project =>
@@ -702,24 +705,45 @@ public void PublishRelease_does_not_override_Configuration_property_across_forma
propertyGroup.Add(new XElement(ns + "PublishRelease", "true"));
});
- new BuildCommand(helloWorldAsset)
- .Execute(configOpt)
- .Should()
- .Pass();
-
- var publishCommand = new DotnetPublishCommand(Log, helloWorldAsset.TestRoot);
-
- publishCommand
- .Execute(configOpt)
- .Should()
- .Pass().And.NotHaveStdErr();
+ new DotnetPublishCommand(Log, helloWorldAsset.TestRoot)
+ .Execute(configOpt)
+ .Should()
+ .Pass().And.NotHaveStdErr();
- var expectedAssetPath = System.IO.Path.Combine(helloWorldAsset.Path, "bin", "Debug", ToolsetInfo.CurrentTargetFramework, "HelloWorld.dll");
+ var expectedAssetPath = Path.Combine(helloWorldAsset.Path, "bin", "Debug", ToolsetInfo.CurrentTargetFramework, "HelloWorld.dll");
Assert.True(File.Exists(expectedAssetPath));
- var releaseAssetPath = System.IO.Path.Combine(helloWorldAsset.Path, "bin", "Release", ToolsetInfo.CurrentTargetFramework, "HelloWorld.dll");
+ var releaseAssetPath = Path.Combine(helloWorldAsset.Path, "bin", "Release", ToolsetInfo.CurrentTargetFramework, "HelloWorld.dll");
Assert.False(File.Exists(releaseAssetPath)); // build will produce a debug asset, need to make sure this doesn't exist either.
}
+ [Theory]
+ [InlineData("")]
+ [InlineData("=")]
+ public void PublishRelease_does_recognize_undefined_property(string propertySuffix)
+ {
+ string tfm = ToolsetInfo.CurrentTargetFramework;
+ var testProject = new TestProject()
+ {
+ IsExe = true,
+ TargetFrameworks = tfm
+ };
+
+ testProject.RecordProperties("SelfContained");
+ testProject.RecordProperties("PublishAot");
+
+ var testAsset = _testAssetsManager.CreateTestProject(testProject);
+ new DotnetPublishCommand(Log)
+ .WithWorkingDirectory(Path.Combine(testAsset.TestRoot, MethodBase.GetCurrentMethod().Name))
+ .Execute(("-p:SelfContained" + propertySuffix))
+ .Should()
+ .Pass();
+
+ var properties = testProject.GetPropertyValues(testAsset.TestRoot, targetFramework: tfm);
+
+ Assert.Equal("", properties["SelfContained"]);
+ Assert.Equal("", properties["PublishAot"]);
+ }
+
[Fact]
public void PublishRelease_does_not_override_Configuration_option()
{