Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 96a93ab

Browse filesBrowse files
[main] Source code updates from dotnet/msbuild (#1296)
[main] Source code updates from dotnet/msbuild
1 parent 1df36b2 commit 96a93ab
Copy full SHA for 96a93ab

File tree

Expand file treeCollapse file tree

11 files changed

+196
-18
lines changed
Filter options
Expand file treeCollapse file tree

11 files changed

+196
-18
lines changed

‎src/msbuild/eng/Version.Details.xml

Copy file name to clipboardExpand all lines: src/msbuild/eng/Version.Details.xml
+2-2Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -116,9 +116,9 @@
116116
<Uri>https://github.com/dotnet/arcade</Uri>
117117
<Sha>0d52a8b262d35fa2fde84e398cb2e791b8454bd2</Sha>
118118
</Dependency>
119-
<Dependency Name="NuGet.Build.Tasks" Version="6.15.0-preview.1.82">
119+
<Dependency Name="NuGet.Build.Tasks" Version="6.15.0-preview.1.86">
120120
<Uri>https://github.com/nuget/nuget.client</Uri>
121-
<Sha>772ee13d2bafaa1414d90dbfbd77e0941115ef19</Sha>
121+
<Sha>eb38c4a6cccfce5ee9415da1a930fc6534194b2b</Sha>
122122
</Dependency>
123123
<Dependency Name="Microsoft.Net.Compilers.Toolset" Version="4.14.0-3.25262.10">
124124
<Uri>https://github.com/dotnet/roslyn</Uri>

‎src/msbuild/eng/Versions.props

Copy file name to clipboardExpand all lines: src/msbuild/eng/Versions.props
+1-1Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@
8181
<DotNetCliVersion>$([System.Text.RegularExpressions.Regex]::Match($([System.IO.File]::ReadAllText('$(MSBuildThisFileDirectory)..\global.json')), '"dotnet": "([^"]*)"').Groups.get_Item(1))</DotNetCliVersion>
8282
<MicrosoftCodeAnalysisCollectionsVersion>4.2.0-1.22102.8</MicrosoftCodeAnalysisCollectionsVersion>
8383
<MicrosoftDotNetXUnitExtensionsVersion>9.0.0-beta.25302.2</MicrosoftDotNetXUnitExtensionsVersion>
84-
<NuGetBuildTasksVersion>6.15.0-preview.1.82</NuGetBuildTasksVersion>
84+
<NuGetBuildTasksVersion>6.15.0-preview.1.86</NuGetBuildTasksVersion>
8585
<MicrosoftNetCompilersToolsetVersion>4.14.0-3.25262.10</MicrosoftNetCompilersToolsetVersion>
8686
</PropertyGroup>
8787
<PropertyGroup Condition="!$(TargetFramework.StartsWith('net4'))">

‎src/msbuild/src/Build.UnitTests/Construction/SolutionFile_OldParser_Tests.cs

Copy file name to clipboardExpand all lines: src/msbuild/src/Build.UnitTests/Construction/SolutionFile_OldParser_Tests.cs
+110-4Lines changed: 110 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -50,14 +50,12 @@ public void BasicParseFirstProjectLine()
5050
/// extension of vcproj is seen as invalid.
5151
/// </summary>
5252
[Fact]
53-
[Trait("Category", "netcore-osx-failing")]
54-
[Trait("Category", "netcore-linux-failing")]
5553
public void ParseFirstProjectLine_VC()
5654
{
5755
Should.Throw<InvalidProjectFileException>(() =>
5856
{
5957
SolutionFile p = new SolutionFile();
60-
p.FullPath = "c:\\foo.sln";
58+
p.FullPath = NativeMethodsShared.IsWindows ? "c:\\foo.sln" : "/foo.sln";
6159
ProjectInSolution proj = new ProjectInSolution(p);
6260

6361
p.ParseFirstProjectLine(
@@ -609,7 +607,9 @@ public void ParseNestedEtpProjectMultipleLevel()
609607
// Project should get added to the solution
610608
solution.ProjectsInOrder[0].RelativePath.ShouldBe(@"someproj.etp");
611609
solution.ProjectsInOrder[1].RelativePath.ShouldBe(@"someproj2.etp");
612-
solution.ProjectsInOrder[2].RelativePath.ShouldBe(@"ETPProjUpgradeTest\someproj3.etp");
610+
// On Unix systems, directory separators should be forward slashes (fixes issue #1769)
611+
string expectedPath3 = NativeMethodsShared.IsWindows ? @"ETPProjUpgradeTest\someproj3.etp" : "ETPProjUpgradeTest/someproj3.etp";
612+
solution.ProjectsInOrder[2].RelativePath.ShouldBe(expectedPath3);
613613
solution.ProjectsInOrder[3].RelativePath.ShouldBe(Path.Combine("ETPProjUpgradeTest", "..", "SomeFolder", "ClassLibrary1.csproj"));
614614
}
615615
// Delete the files created during the test
@@ -2482,5 +2482,111 @@ public void ParseSolutionWithComments()
24822482

24832483
Should.NotThrow(() => ParseSolutionHelper(stringBuilder.ToString()));
24842484
}
2485+
2486+
/// <summary>
2487+
/// Test for issue #1769 - ProjectInSolution.AbsolutePath contains '\' on Mac OS/Linux
2488+
/// Ensure that AbsolutePath uses forward slashes on Unix systems even when the solution
2489+
/// file contains project paths with backslashes.
2490+
/// </summary>
2491+
[Fact]
2492+
[SkipOnPlatform(TestPlatforms.Windows, "Unix-specific test")]
2493+
public void AbsolutePathShouldUseForwardSlashesOnUnix()
2494+
{
2495+
2496+
string solutionFileContents =
2497+
@"
2498+
Microsoft Visual Studio Solution File, Format Version 12.00
2499+
# Visual Studio Version 16
2500+
VisualStudioVersion = 16.0.30114.105
2501+
MinimumVisualStudioVersion = 10.0.40219.1
2502+
Project('{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}') = 'ProjectInSolutionRepro', 'ProjectInSolutionRepro\ProjectInSolutionRepro.csproj', '{GUID-HERE}'
2503+
EndProject
2504+
Global
2505+
EndGlobal
2506+
";
2507+
2508+
SolutionFile solution = ParseSolutionHelper(solutionFileContents);
2509+
2510+
solution.ProjectsInOrder.Count.ShouldBe(1);
2511+
ProjectInSolution project = solution.ProjectsInOrder[0];
2512+
2513+
project.ProjectName.ShouldBe("ProjectInSolutionRepro");
2514+
2515+
// The AbsolutePath should not contain backslashes on Unix systems
2516+
project.AbsolutePath.ShouldNotContain("\\");
2517+
2518+
// The AbsolutePath should contain forward slashes (unless it's just a filename)
2519+
if (project.AbsolutePath.Contains(Path.DirectorySeparatorChar.ToString()))
2520+
{
2521+
project.AbsolutePath.ShouldContain("/");
2522+
}
2523+
}
2524+
2525+
/// <summary>
2526+
/// Test for edge case where RelativePath could be treated as an absolute URI
2527+
/// and bypass normalization, leading to backslashes in AbsolutePath on Unix.
2528+
/// </summary>
2529+
[Fact]
2530+
[SkipOnPlatform(TestPlatforms.Windows, "Unix-specific test")]
2531+
public void AbsolutePathShouldHandleUriLikeRelativePathsOnUnix()
2532+
{
2533+
2534+
// Test with a path that might be interpreted as a URI
2535+
string solutionFileContents =
2536+
@"
2537+
Microsoft Visual Studio Solution File, Format Version 12.00
2538+
Project('{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}') = 'WebProject', 'http://localhost\path\to\project', '{GUID-HERE}'
2539+
EndProject
2540+
Global
2541+
EndGlobal
2542+
";
2543+
2544+
SolutionFile solution = ParseSolutionHelper(solutionFileContents);
2545+
2546+
solution.ProjectsInOrder.Count.ShouldBe(1);
2547+
ProjectInSolution project = solution.ProjectsInOrder[0];
2548+
2549+
// Even if the RelativePath looks like a URI, AbsolutePath should not contain backslashes on Unix
2550+
if (project.AbsolutePath.Contains("\\"))
2551+
{
2552+
project.AbsolutePath.ShouldNotContain("\\");
2553+
}
2554+
}
2555+
2556+
/// <summary>
2557+
/// Test to verify that the fix for issue #1769 works by directly testing
2558+
/// FileUtilities.FixFilePath integration in AbsolutePath.
2559+
/// This test simulates scenarios where intermediate path processing might
2560+
/// leave backslashes in the AbsolutePath on Unix systems.
2561+
/// </summary>
2562+
[Fact]
2563+
[SkipOnPlatform(TestPlatforms.Windows, "Unix-specific test")]
2564+
public void AbsolutePathFixFilePathIntegrationTest()
2565+
{
2566+
2567+
string solutionFileContents =
2568+
@"
2569+
Microsoft Visual Studio Solution File, Format Version 12.00
2570+
Project('{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}') = 'TestProject', 'Sub\Dir\Project.csproj', '{GUID-HERE}'
2571+
EndProject
2572+
Global
2573+
EndGlobal
2574+
";
2575+
2576+
SolutionFile solution = ParseSolutionHelper(solutionFileContents);
2577+
2578+
solution.ProjectsInOrder.Count.ShouldBe(1);
2579+
ProjectInSolution project = solution.ProjectsInOrder[0];
2580+
2581+
// This test verifies that regardless of what happens in intermediate processing,
2582+
// the final AbsolutePath result never contains backslashes on Unix
2583+
project.AbsolutePath.ShouldNotContain("\\");
2584+
2585+
// Verify that the path contains forward slashes as expected
2586+
project.AbsolutePath.ShouldContain("/");
2587+
2588+
// Verify that the path structure is still correct (should contain the subdirectory)
2589+
project.AbsolutePath.ShouldContain("Sub");
2590+
}
24852591
}
24862592
}

‎src/msbuild/src/Build.UnitTests/Evaluation/Expander_Tests.cs

Copy file name to clipboardExpand all lines: src/msbuild/src/Build.UnitTests/Evaluation/Expander_Tests.cs
+25Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4741,6 +4741,31 @@ public void PropertyFunctionStringArrayGetValue()
47414741
TestPropertyFunction("$(X.Split($([System.Convert]::ToString(`.`).ToCharArray())).GetValue($([System.Convert]::ToInt32(0))))", "X", "ab.cd", "ab");
47424742
}
47434743

4744+
/// <summary>
4745+
/// Test that Char.IsDigit fast-path works correctly
4746+
/// </summary>
4747+
[Theory]
4748+
// Test with digit characters - single char version
4749+
[InlineData("$([System.Char]::IsDigit('0'))", "True")]
4750+
[InlineData("$([System.Char]::IsDigit('5'))", "True")]
4751+
[InlineData("$([System.Char]::IsDigit('9'))", "True")]
4752+
// Test with non-digit characters - single char version
4753+
[InlineData("$([System.Char]::IsDigit('a'))", "False")]
4754+
[InlineData("$([System.Char]::IsDigit(' '))", "False")]
4755+
[InlineData("$([System.Char]::IsDigit('/'))", "False")]
4756+
[InlineData("$([System.Char]::IsDigit(':'))", "False")]
4757+
// Test with string and index version
4758+
[InlineData("$([System.Char]::IsDigit('abc123def', 3))", "True")]
4759+
[InlineData("$([System.Char]::IsDigit('abc123def', 4))", "True")]
4760+
[InlineData("$([System.Char]::IsDigit('abc123def', 5))", "True")]
4761+
[InlineData("$([System.Char]::IsDigit('abc123def', 0))", "False")]
4762+
[InlineData("$([System.Char]::IsDigit('abc123def', 2))", "False")]
4763+
[InlineData("$([System.Char]::IsDigit('hello789', 5))", "True")]
4764+
public void PropertyFunctionCharIsDigit(string expression, string expected)
4765+
{
4766+
TestPropertyFunction(expression, "dummy", "", expected);
4767+
}
4768+
47444769
private void TestPropertyFunction(string expression, string propertyName, string propertyValue, string expected)
47454770
{
47464771
var properties = new PropertyDictionary<ProjectPropertyInstance>();

‎src/msbuild/src/Build.UnitTests/Evaluation/ItemEvaluation_Tests.cs

Copy file name to clipboardExpand all lines: src/msbuild/src/Build.UnitTests/Evaluation/ItemEvaluation_Tests.cs
+1-1Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -693,7 +693,7 @@ public void DifferentExcludesOnSameWildcardProduceDifferentResults(bool cacheFil
693693
}
694694
finally
695695
{
696-
FileMatcher.ClearFileEnumerationsCache();
696+
FileMatcher.ClearCaches();
697697
}
698698
}
699699

‎src/msbuild/src/Build/BackEnd/BuildManager/BuildManager.cs

Copy file name to clipboardExpand all lines: src/msbuild/src/Build/BackEnd/BuildManager/BuildManager.cs
+1-1Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2817,7 +2817,7 @@ private void CheckAllSubmissionsComplete(BuildRequestDataFlags? flags)
28172817
// part of the import graph.
28182818
_buildParameters?.ProjectRootElementCache?.Clear();
28192819

2820-
FileMatcher.ClearFileEnumerationsCache();
2820+
FileMatcher.ClearCaches();
28212821
#if !CLR2COMPATIBILITY
28222822
FileUtilities.ClearFileExistenceCache();
28232823
#endif

‎src/msbuild/src/Build/BackEnd/TaskExecutionHost/TaskExecutionHost.cs

Copy file name to clipboardExpand all lines: src/msbuild/src/Build/BackEnd/TaskExecutionHost/TaskExecutionHost.cs
+4-3Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1226,16 +1226,17 @@ private void EnsureParameterInitialized(TaskPropertyInfo parameter, Lookup looku
12261226

12271227
parameter.Initialized = true;
12281228

1229-
string taskAndParameterName = _taskName + "_" + parameter.Name;
1230-
string key = "DisableLogTaskParameter_" + taskAndParameterName;
1229+
// PERF: Be careful to avoid unnecessary string allocations. Appending '_taskName + "_" + parameter.Name' happens in both paths,
1230+
// but we don't want to allocate the string if we don't need to.
1231+
string key = "DisableLogTaskParameter_" + _taskName + "_" + parameter.Name;
12311232

12321233
if (string.Equals(lookup.GetProperty(key)?.EvaluatedValue, "true", StringComparison.OrdinalIgnoreCase))
12331234
{
12341235
parameter.Log = false;
12351236
}
12361237
else
12371238
{
1238-
string metadataKey = "DisableLogTaskParameterItemMetadata_" + taskAndParameterName;
1239+
string metadataKey = "DisableLogTaskParameterItemMetadata_" + _taskName + "_" + parameter.Name;
12391240
if (string.Equals(lookup.GetProperty(metadataKey)?.EvaluatedValue, "true", StringComparison.OrdinalIgnoreCase))
12401241
{
12411242
parameter.LogItemMetadata = false;

‎src/msbuild/src/Build/Evaluation/Expander/WellKnownFunctions.cs

Copy file name to clipboardExpand all lines: src/msbuild/src/Build/Evaluation/Expander/WellKnownFunctions.cs
+23Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -875,6 +875,29 @@ internal static bool TryExecuteWellKnownFunction(string methodName, Type receive
875875
}
876876
}
877877
}
878+
else if (receiverType == typeof(char))
879+
{
880+
if (string.Equals(methodName, nameof(char.IsDigit), StringComparison.OrdinalIgnoreCase))
881+
{
882+
bool? result = null;
883+
884+
if (ParseArgs.TryGetArg(args, out string? arg0) && arg0?.Length == 1)
885+
{
886+
char c = arg0[0];
887+
result = char.IsDigit(c);
888+
}
889+
else if (ParseArgs.TryGetArgs(args, out string? str, out int index) && str != null)
890+
{
891+
result = char.IsDigit(str, index);
892+
}
893+
894+
if (result.HasValue)
895+
{
896+
returnVal = result.Value;
897+
return true;
898+
}
899+
}
900+
}
878901
else if (string.Equals(methodName, nameof(Regex.Replace), StringComparison.OrdinalIgnoreCase) && args.Length == 3)
879902
{
880903
if (ParseArgs.TryGetArgs(args, out string? arg1, out string? arg2, out string? arg3) && arg1 != null && arg2 != null && arg3 != null)

‎src/msbuild/src/Shared/FileMatcher.cs

Copy file name to clipboardExpand all lines: src/msbuild/src/Shared/FileMatcher.cs
+25-2Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ internal class FileMatcher
3838
private static readonly char[] s_wildcardCharacters = { '*', '?' };
3939
private static readonly char[] s_wildcardAndSemicolonCharacters = { '*', '?', ';' };
4040

41+
4142
#if NET
4243
private static readonly SearchValues<string> s_propertyAndItemReferences = SearchValues.Create(["$(", "@("], StringComparison.Ordinal);
4344
#else
@@ -50,6 +51,7 @@ internal class FileMatcher
5051
// until Cloudbuild switches to EvaluationContext, we need to keep their dependence on global glob caching via an environment variable
5152
private static readonly Lazy<ConcurrentDictionary<string, IReadOnlyList<string>>> s_cachedGlobExpansions = new Lazy<ConcurrentDictionary<string, IReadOnlyList<string>>>(() => new ConcurrentDictionary<string, IReadOnlyList<string>>(StringComparer.OrdinalIgnoreCase));
5253
private static readonly Lazy<ConcurrentDictionary<string, object>> s_cachedGlobExpansionsLock = new Lazy<ConcurrentDictionary<string, object>>(() => new ConcurrentDictionary<string, object>(StringComparer.OrdinalIgnoreCase));
54+
private static readonly Lazy<ConcurrentDictionary<string, (Regex regex, bool needsRecursion, bool isLegalFileSpec)>> s_regexCache = new(() =>new(StringComparer.Ordinal));
5355

5456
private readonly ConcurrentDictionary<string, IReadOnlyList<string>> _cachedGlobExpansions;
5557
private readonly Lazy<ConcurrentDictionary<string, object>> _cachedGlobExpansionsLock = new Lazy<ConcurrentDictionary<string, object>>(() => new ConcurrentDictionary<string, object>(StringComparer.OrdinalIgnoreCase));
@@ -165,7 +167,7 @@ internal enum FileSystemEntity
165167
/// <returns>An enumerable of filesystem entries.</returns>
166168
internal delegate IReadOnlyList<string> GetFileSystemEntries(FileSystemEntity entityType, string path, string pattern, string projectDirectory, bool stripProjectDirectory);
167169

168-
internal static void ClearFileEnumerationsCache()
170+
internal static void ClearCaches()
169171
{
170172
if (s_cachedGlobExpansions.IsValueCreated)
171173
{
@@ -176,6 +178,10 @@ internal static void ClearFileEnumerationsCache()
176178
{
177179
s_cachedGlobExpansionsLock.Value.Clear();
178180
}
181+
if (s_regexCache.IsValueCreated)
182+
{
183+
s_regexCache.Value.Clear();
184+
}
179185
}
180186

181187
/// <summary>
@@ -1486,7 +1492,7 @@ private static int LastIndexOfDirectoryOrRecursiveSequence(string str, int start
14861492
/// <param name="regexFileMatch">Receives the regular expression.</param>
14871493
/// <param name="needsRecursion">Receives the flag that is true if recursion is required.</param>
14881494
/// <param name="isLegalFileSpec">Receives the flag that is true if the filespec is legal.</param>
1489-
internal void GetFileSpecInfoWithRegexObject(
1495+
internal void GetFileSpecInfoWithRegexObjectCore(
14901496
string filespec,
14911497
out Regex regexFileMatch,
14921498
out bool needsRecursion,
@@ -1507,6 +1513,23 @@ internal void GetFileSpecInfoWithRegexObject(
15071513
}
15081514
}
15091515

1516+
// PERF: Cache the Regex generation to avoid repeated allocations.
1517+
internal void GetFileSpecInfoWithRegexObject(
1518+
string filespec,
1519+
out Regex regexFileMatch,
1520+
out bool needsRecursion,
1521+
out bool isLegalFileSpec)
1522+
{
1523+
var result = s_regexCache.Value.GetOrAdd(filespec, spec =>
1524+
{
1525+
GetFileSpecInfoWithRegexObjectCore(spec, out var regex, out var needsRec, out var isLegal);
1526+
return (regex, needsRec, isLegal);
1527+
});
1528+
regexFileMatch = result.regex;
1529+
needsRecursion = result.needsRecursion;
1530+
isLegalFileSpec = result.isLegalFileSpec;
1531+
}
1532+
15101533
internal delegate (string fixedDirectoryPart, string recursiveDirectoryPart, string fileNamePart) FixupParts(
15111534
string fixedDirectoryPart,
15121535
string recursiveDirectoryPart,

‎src/msbuild/src/Shared/UnitTests/FileMatcher_Tests.cs

Copy file name to clipboardExpand all lines: src/msbuild/src/Shared/UnitTests/FileMatcher_Tests.cs
+1-1Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1300,7 +1300,7 @@ public void FileEnumerationCacheTakesExcludesIntoAccount()
13001300
}
13011301
finally
13021302
{
1303-
FileMatcher.ClearFileEnumerationsCache();
1303+
FileMatcher.ClearCaches();
13041304
}
13051305
}
13061306

‎src/source-manifest.json

Copy file name to clipboardExpand all lines: src/source-manifest.json
+3-3Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -71,11 +71,11 @@
7171
"commitSha": "733acd8bae809f1535c10576fba2fb86a65f6c1a"
7272
},
7373
{
74-
"packageVersion": "17.15.0-preview-25320-08",
75-
"barId": 272622,
74+
"packageVersion": "17.15.0-preview-25323-07",
75+
"barId": 272804,
7676
"path": "msbuild",
7777
"remoteUri": "https://github.com/dotnet/msbuild",
78-
"commitSha": "559acc5f77929ea5092c7395d84ddab469d2f554"
78+
"commitSha": "f526ea3d9bcdc417c10ce157b673042773ca97f9"
7979
},
8080
{
8181
"packageVersion": "6.15.0-preview.1.82",

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.