Split arguments for the build server properly
This commit is contained in:
parent
84beb5985f
commit
ba7f955afa
|
|
@ -168,11 +168,10 @@ namespace Microsoft.AspNetCore.Razor.Tasks
|
||||||
return workingDirectory;
|
return workingDirectory;
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<string> GetArguments(string responseFileCommands)
|
private IList<string> GetArguments(string responseFileCommands)
|
||||||
{
|
{
|
||||||
var responseFileArguments =
|
var list = responseFileCommands.Split(new[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries);
|
||||||
CommandLineUtilities.SplitCommandLineIntoArguments(responseFileCommands, removeHashComments: true);
|
return list;
|
||||||
return responseFileArguments.ToList();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override bool HandleTaskExecutionErrors()
|
protected override bool HandleTaskExecutionErrors()
|
||||||
|
|
|
||||||
|
|
@ -22,9 +22,6 @@
|
||||||
<Compile Include="..\Microsoft.AspNetCore.Razor.Tools\Roslyn\PlatformInformation.cs">
|
<Compile Include="..\Microsoft.AspNetCore.Razor.Tools\Roslyn\PlatformInformation.cs">
|
||||||
<Link>Shared\PlatformInformation.cs</Link>
|
<Link>Shared\PlatformInformation.cs</Link>
|
||||||
</Compile>
|
</Compile>
|
||||||
<Compile Include="..\Microsoft.AspNetCore.Razor.Tools\Roslyn\CommandLineUtilities.cs">
|
|
||||||
<Link>Shared\CommandLineUtilities.cs</Link>
|
|
||||||
</Compile>
|
|
||||||
<Compile Include="..\Microsoft.AspNetCore.Razor.Tools\ServerProtocol\*.cs">
|
<Compile Include="..\Microsoft.AspNetCore.Razor.Tools\ServerProtocol\*.cs">
|
||||||
<Link>Shared\ServerProtocol\%(FileName)</Link>
|
<Link>Shared\ServerProtocol\%(FileName)</Link>
|
||||||
</Compile>
|
</Compile>
|
||||||
|
|
|
||||||
|
|
@ -1,154 +0,0 @@
|
||||||
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
|
||||||
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Text;
|
|
||||||
|
|
||||||
namespace Roslyn.Utilities
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
* Copied from https://github.com/dotnet/roslyn/blob/master/src/Compilers/Core/Portable/InternalUtilities/CommandLineUtilities.cs
|
|
||||||
*/
|
|
||||||
internal static class CommandLineUtilities
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Split a command line by the same rules as Main would get the commands except the original
|
|
||||||
/// state of backslashes and quotes are preserved. For example in normal Windows command line
|
|
||||||
/// parsing the following command lines would produce equivalent Main arguments:
|
|
||||||
///
|
|
||||||
/// - /r:a,b
|
|
||||||
/// - /r:"a,b"
|
|
||||||
///
|
|
||||||
/// This method will differ as the latter will have the quotes preserved. The only case where
|
|
||||||
/// quotes are removed is when the entire argument is surrounded by quotes without any inner
|
|
||||||
/// quotes.
|
|
||||||
/// </summary>
|
|
||||||
/// <remarks>
|
|
||||||
/// Rules for command line parsing, according to MSDN:
|
|
||||||
///
|
|
||||||
/// Arguments are delimited by white space, which is either a space or a tab.
|
|
||||||
///
|
|
||||||
/// A string surrounded by double quotation marks ("string") is interpreted
|
|
||||||
/// as a single argument, regardless of white space contained within.
|
|
||||||
/// A quoted string can be embedded in an argument.
|
|
||||||
///
|
|
||||||
/// A double quotation mark preceded by a backslash (\") is interpreted as a
|
|
||||||
/// literal double quotation mark character (").
|
|
||||||
///
|
|
||||||
/// Backslashes are interpreted literally, unless they immediately precede a
|
|
||||||
/// double quotation mark.
|
|
||||||
///
|
|
||||||
/// If an even number of backslashes is followed by a double quotation mark,
|
|
||||||
/// one backslash is placed in the argv array for every pair of backslashes,
|
|
||||||
/// and the double quotation mark is interpreted as a string delimiter.
|
|
||||||
///
|
|
||||||
/// If an odd number of backslashes is followed by a double quotation mark,
|
|
||||||
/// one backslash is placed in the argv array for every pair of backslashes,
|
|
||||||
/// and the double quotation mark is "escaped" by the remaining backslash,
|
|
||||||
/// causing a literal double quotation mark (") to be placed in argv.
|
|
||||||
/// </remarks>
|
|
||||||
public static IEnumerable<string> SplitCommandLineIntoArguments(string commandLine, bool removeHashComments)
|
|
||||||
{
|
|
||||||
return SplitCommandLineIntoArguments(commandLine, removeHashComments, out var unused);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static IEnumerable<string> SplitCommandLineIntoArguments(string commandLine, bool removeHashComments, out char? illegalChar)
|
|
||||||
{
|
|
||||||
var builder = new StringBuilder(commandLine.Length);
|
|
||||||
var list = new List<string>();
|
|
||||||
var i = 0;
|
|
||||||
|
|
||||||
illegalChar = null;
|
|
||||||
while (i < commandLine.Length)
|
|
||||||
{
|
|
||||||
while (i < commandLine.Length && char.IsWhiteSpace(commandLine[i]))
|
|
||||||
{
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (i == commandLine.Length)
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (commandLine[i] == '#' && removeHashComments)
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
var quoteCount = 0;
|
|
||||||
builder.Length = 0;
|
|
||||||
while (i < commandLine.Length && (!char.IsWhiteSpace(commandLine[i]) || (quoteCount % 2 != 0)))
|
|
||||||
{
|
|
||||||
var current = commandLine[i];
|
|
||||||
switch (current)
|
|
||||||
{
|
|
||||||
case '\\':
|
|
||||||
{
|
|
||||||
var slashCount = 0;
|
|
||||||
do
|
|
||||||
{
|
|
||||||
builder.Append(commandLine[i]);
|
|
||||||
i++;
|
|
||||||
slashCount++;
|
|
||||||
} while (i < commandLine.Length && commandLine[i] == '\\');
|
|
||||||
|
|
||||||
// Slashes not followed by a quote character can be ignored for now
|
|
||||||
if (i >= commandLine.Length || commandLine[i] != '"')
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If there is an odd number of slashes then it is escaping the quote
|
|
||||||
// otherwise it is just a quote.
|
|
||||||
if (slashCount % 2 == 0)
|
|
||||||
{
|
|
||||||
quoteCount++;
|
|
||||||
}
|
|
||||||
|
|
||||||
builder.Append('"');
|
|
||||||
i++;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case '"':
|
|
||||||
builder.Append(current);
|
|
||||||
quoteCount++;
|
|
||||||
i++;
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
if ((current >= 0x1 && current <= 0x1f) || current == '|')
|
|
||||||
{
|
|
||||||
if (illegalChar == null)
|
|
||||||
{
|
|
||||||
illegalChar = current;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
builder.Append(current);
|
|
||||||
}
|
|
||||||
|
|
||||||
i++;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// If the quote string is surrounded by quotes with no interior quotes then
|
|
||||||
// remove the quotes here.
|
|
||||||
if (quoteCount == 2 && builder[0] == '"' && builder[builder.Length - 1] == '"')
|
|
||||||
{
|
|
||||||
builder.Remove(0, length: 1);
|
|
||||||
builder.Remove(builder.Length - 1, length: 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (builder.Length > 0)
|
|
||||||
{
|
|
||||||
list.Add(builder.ToString());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return list;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -84,7 +84,7 @@ namespace Microsoft.AspNetCore.Razor.Tools
|
||||||
|
|
||||||
public static Task<ServerResponse> RunOnServer(
|
public static Task<ServerResponse> RunOnServer(
|
||||||
string pipeName,
|
string pipeName,
|
||||||
List<string> arguments,
|
IList<string> arguments,
|
||||||
ServerPaths buildPaths,
|
ServerPaths buildPaths,
|
||||||
CancellationToken cancellationToken,
|
CancellationToken cancellationToken,
|
||||||
string keepAlive = null,
|
string keepAlive = null,
|
||||||
|
|
@ -107,7 +107,7 @@ namespace Microsoft.AspNetCore.Razor.Tools
|
||||||
}
|
}
|
||||||
|
|
||||||
private static async Task<ServerResponse> RunOnServerCore(
|
private static async Task<ServerResponse> RunOnServerCore(
|
||||||
List<string> arguments,
|
IList<string> arguments,
|
||||||
ServerPaths buildPaths,
|
ServerPaths buildPaths,
|
||||||
string pipeName,
|
string pipeName,
|
||||||
string keepAlive,
|
string keepAlive,
|
||||||
|
|
|
||||||
|
|
@ -33,5 +33,20 @@ namespace Microsoft.AspNetCore.Razor.Design.IntegrationTests
|
||||||
Assert.FileExists(result, OutputPath, "SimpleMvc.PrecompiledViews.dll");
|
Assert.FileExists(result, OutputPath, "SimpleMvc.PrecompiledViews.dll");
|
||||||
Assert.FileExists(result, OutputPath, "SimpleMvc.PrecompiledViews.pdb");
|
Assert.FileExists(result, OutputPath, "SimpleMvc.PrecompiledViews.pdb");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
[InitializeTestProject("SimpleMvc", baseDirectory: "Whitespace in path", additionalProjects: new string[] { })]
|
||||||
|
public async Task Build_AppWithWhitespaceInPath_CanBuildSuccessfully()
|
||||||
|
{
|
||||||
|
var result = await DotnetMSBuild(
|
||||||
|
"Build",
|
||||||
|
$"/p:RazorCompileOnBuild=true /p:UseRazorBuildServer=true /p:_RazorBuildServerPipeName={_pipeName}");
|
||||||
|
|
||||||
|
Assert.BuildPassed(result);
|
||||||
|
Assert.FileExists(result, OutputPath, "SimpleMvc.dll");
|
||||||
|
Assert.FileExists(result, OutputPath, "SimpleMvc.pdb");
|
||||||
|
Assert.FileExists(result, OutputPath, "SimpleMvc.PrecompiledViews.dll");
|
||||||
|
Assert.FileExists(result, OutputPath, "SimpleMvc.PrecompiledViews.pdb");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -10,11 +10,18 @@ namespace Microsoft.AspNetCore.Razor.Design.IntegrationTests
|
||||||
public class InitializeTestProjectAttribute : BeforeAfterTestAttribute
|
public class InitializeTestProjectAttribute : BeforeAfterTestAttribute
|
||||||
{
|
{
|
||||||
private readonly string _projectName;
|
private readonly string _projectName;
|
||||||
|
private readonly string _baseDirectory;
|
||||||
private readonly string[] _additionalProjects;
|
private readonly string[] _additionalProjects;
|
||||||
|
|
||||||
public InitializeTestProjectAttribute(string projectName, params string[] additionalProjects)
|
public InitializeTestProjectAttribute(string projectName, params string[] additionalProjects)
|
||||||
|
: this (projectName, string.Empty, additionalProjects)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public InitializeTestProjectAttribute(string projectName, string baseDirectory, string[] additionalProjects)
|
||||||
{
|
{
|
||||||
_projectName = projectName;
|
_projectName = projectName;
|
||||||
|
_baseDirectory = baseDirectory;
|
||||||
_additionalProjects = additionalProjects;
|
_additionalProjects = additionalProjects;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -25,7 +32,7 @@ namespace Microsoft.AspNetCore.Razor.Design.IntegrationTests
|
||||||
throw new InvalidOperationException($"This should be used on a class derived from {typeof(MSBuildIntegrationTestBase)}");
|
throw new InvalidOperationException($"This should be used on a class derived from {typeof(MSBuildIntegrationTestBase)}");
|
||||||
}
|
}
|
||||||
|
|
||||||
MSBuildIntegrationTestBase.Project = ProjectDirectory.Create(_projectName, _additionalProjects);
|
MSBuildIntegrationTestBase.Project = ProjectDirectory.Create(_projectName, _baseDirectory, _additionalProjects);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void After(MethodInfo methodUnderTest)
|
public override void After(MethodInfo methodUnderTest)
|
||||||
|
|
|
||||||
|
|
@ -18,9 +18,9 @@ namespace Microsoft.AspNetCore.Razor.Design.IntegrationTests
|
||||||
public bool PreserveWorkingDirectory { get; set; }
|
public bool PreserveWorkingDirectory { get; set; }
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
public static ProjectDirectory Create(string projectName, string[] additionalProjects)
|
public static ProjectDirectory Create(string projectName, string baseDirectory, string[] additionalProjects)
|
||||||
{
|
{
|
||||||
var destinationPath = Path.Combine(Path.GetTempPath(), "Razor", Path.GetRandomFileName());
|
var destinationPath = Path.Combine(Path.GetTempPath(), "Razor", baseDirectory, Path.GetRandomFileName());
|
||||||
Directory.CreateDirectory(destinationPath);
|
Directory.CreateDirectory(destinationPath);
|
||||||
|
|
||||||
try
|
try
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue