Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Do not collapse slashes #1641

Closed
wants to merge 6 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/Build.UnitTests/BackEnd/IntrinsicTask_Tests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2098,15 +2098,15 @@ public void RemoveWithWildcards()
<Target Name='t'>
<ItemGroup>
<i1 Include='" + files.First() + ";" + files.ElementAt(1) + @";other'/>
<i1 Remove='$(temp)" + Path.DirectorySeparatorChar + @"*.tmp'/>
<i1 Remove='$(temp)*.tmp'/>
</ItemGroup>
</Target></Project>");
IntrinsicTask task = CreateIntrinsicTask(content);
PropertyDictionary<ProjectPropertyInstance> properties = new PropertyDictionary<ProjectPropertyInstance>();
properties.Set(
ProjectPropertyInstance.Create(
"TEMP",
NativeMethodsShared.IsWindows ? Environment.GetEnvironmentVariable("TEMP") : Path.GetTempPath()));
FileUtilities.EnsureTrailingSlash(NativeMethodsShared.IsWindows ? Environment.GetEnvironmentVariable("TEMP") : Path.GetTempPath())));
Lookup lookup = LookupHelpers.CreateLookup(properties);
ExecuteTask(task, lookup);

Expand Down
138 changes: 138 additions & 0 deletions src/Build.UnitTests/Evaluation/EvaluatorFileNormalization_Tests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
//-----------------------------------------------------------------------
// </copyright>
// <summary>Tests for evaluation</summary>
//-----------------------------------------------------------------------

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Linq.Expressions;
using System.Xml;

using Microsoft.Build.Evaluation;
using Microsoft.Build.Shared;
using Xunit;

namespace Microsoft.Build.UnitTests.Evaluation
{
/// <summary>
/// Tests mainly for how evaluation normalizes input for cross-platform paths
/// </summary>
public class EvaluatorFileNormalization_Tests : IDisposable
{
public EvaluatorFileNormalization_Tests()
{
ProjectCollection.GlobalProjectCollection.UnloadAllProjects();
GC.Collect();
}

/// <summary>
/// Cleanup
/// </summary>
public void Dispose()
{
ProjectCollection.GlobalProjectCollection.UnloadAllProjects();
GC.Collect();
}

[Theory]
[InlineData(@"/bin/a//x\\c;ba://", new string[0], true)]
[InlineData(@"/shouldNotExistAtRootLevel/a//x\\c;ba://", new string[0], false)]
[InlineData(@"a/b//x\\c;ba://", new[] { "b/a.txt" }, false)]
[InlineData(@"a/b//x\\c;ba://", new[] { "a/a.txt" }, true)]
public void MultipleForwardSlashesShouldNotGetCollapsedWhenPathLooksLikeUnixPath(string stringLookingLikeUnixPath, string[] intermediateFiles, bool firstPathFragmentExists)
{
string content = ObjectModelHelpers.CleanupFileContents(@"
<Project>
<PropertyGroup>
<P>{0}</P>
</PropertyGroup>
<ItemGroup>
<I Include=""$(p)""/>
</ItemGroup>

<Target Name=""Build"">
<ItemGroup>
<T Include=""$(p)""/>
</ItemGroup>
<Message Text=""GP[$(GP)]"" Importance=""High""/>
<Message Text=""P[$(P)]"" Importance=""High""/>
<Message Text=""I[@(I)]"" Importance=""High""/>
<Message Text=""T[@(T)]"" Importance=""High""/>
</Target>
</Project>");

content = string.Format(content, stringLookingLikeUnixPath);

using (var testFiles = new Helpers.TestProjectWithFiles(content, intermediateFiles))
{
IDictionary<string, string> globalProperties = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
globalProperties.Add("GP", stringLookingLikeUnixPath);

Project project = new Project(testFiles.ProjectFile, globalProperties, null);

MockLogger logger = new MockLogger();
bool result = project.Build(logger);
Assert.Equal(true, result);

var expectedString = firstPathFragmentExists
? NativeMethodsShared.IsWindows ? stringLookingLikeUnixPath : stringLookingLikeUnixPath.ToSlash()
: stringLookingLikeUnixPath;

logger.AssertLogContains($"GP[{expectedString}]");
logger.AssertLogContains($"P[{expectedString}]");
logger.AssertLogContains($"I[{expectedString}]");
logger.AssertLogContains($"T[{expectedString}]");

Assert.Equal(expectedString, project.GetPropertyValue("GP"));
Assert.Equal(expectedString, project.GetPropertyValue("P"));
Assert.Equal(expectedString, string.Join(";", project.Items.Select(i => i.EvaluatedInclude)));
}
}

[Fact]
public void DoubleSlashCausesItemMissmatchForExcludeAndRemove()
{
var content = ObjectModelHelpers.CleanupFileContents(
@"<Project>
<ItemGroup>
<I Include='a//b//**' Exclude='a/b/*.foo'/>
<I2 Include='a/b/**' Exclude='a//b/*.foo'/>
</ItemGroup>

<Target Name='Build'>
<ItemGroup>
<T Include='a/b/**'/>
<T Remove='a//b/*.foo'/>
<T Remove='a/b//*.foo'/>
</ItemGroup>
<Message Text='I[@(I)]' Importance='High'/>
<Message Text='I2[@(I2)]' Importance='High'/>
<Message Text='T[@(T)]' Importance='High'/>
</Target>
</Project>");

using (var testFiles = new Helpers.TestProjectWithFiles(content, new[] { "a/b/a.cs", "a/b/b.foo" }))
{
var project = new Project(testFiles.ProjectFile);

var logger = new MockLogger();
var result = project.Build(logger);
Assert.Equal(true, result);

var expectedI = @"a//b//a.cs;a//b//b.foo";
var expectedI2 = @"a/b/a.cs;a/b/b.foo";

Assert.Equal(expectedI, string.Join(";", project.GetItems("I").Select(_ => _.EvaluatedInclude)));
Assert.Equal(expectedI2, string.Join(";", project.GetItems("I2").Select(_ => _.EvaluatedInclude)));

logger.AssertLogContains($"I[{expectedI}]");
logger.AssertLogContains($"I2[{expectedI2}]");
logger.AssertLogContains($"T[{expectedI2}]");
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,7 @@
<Compile Include="EscapingInProjects_Tests.cs" />
<Compile Include="Evaluation\ItemEvaluation_Tests.cs" />
<Compile Include="Evaluation\Evaluator_Tests.cs" />
<Compile Include="Evaluation\EvaluatorFileNormalization_Tests.cs" />
<Compile Include="Evaluation\Expander_Tests.cs" />
<Compile Include="Evaluation\ExpressionShredder_Tests.cs" />
<Compile Include="Evaluation\ImportFromMSBuildExtensionsPath_Tests.cs" />
Expand Down
4 changes: 2 additions & 2 deletions src/Shared/FileUtilities.cs
Original file line number Diff line number Diff line change
Expand Up @@ -413,8 +413,8 @@ internal static string MaybeAdjustFilePath(string value)
return value;
}

// For Unix-like systems, we may want to convert backslashes to slashes
string newValue = Regex.Replace(value, @"[\\/]+", "/");
// For Unix-like systems, we want to convert backslashes to slashes
string newValue = value.ToSlash();

string quote = string.Empty;
// Find the part of the name we want to check, that is remove quotes, if present
Expand Down