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;
|
||||
}
|
||||
|
||||
private List<string> GetArguments(string responseFileCommands)
|
||||
private IList<string> GetArguments(string responseFileCommands)
|
||||
{
|
||||
var responseFileArguments =
|
||||
CommandLineUtilities.SplitCommandLineIntoArguments(responseFileCommands, removeHashComments: true);
|
||||
return responseFileArguments.ToList();
|
||||
var list = responseFileCommands.Split(new[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries);
|
||||
return list;
|
||||
}
|
||||
|
||||
protected override bool HandleTaskExecutionErrors()
|
||||
|
|
|
|||
|
|
@ -22,9 +22,6 @@
|
|||
<Compile Include="..\Microsoft.AspNetCore.Razor.Tools\Roslyn\PlatformInformation.cs">
|
||||
<Link>Shared\PlatformInformation.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Microsoft.AspNetCore.Razor.Tools\Roslyn\CommandLineUtilities.cs">
|
||||
<Link>Shared\CommandLineUtilities.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Microsoft.AspNetCore.Razor.Tools\ServerProtocol\*.cs">
|
||||
<Link>Shared\ServerProtocol\%(FileName)</Link>
|
||||
</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(
|
||||
string pipeName,
|
||||
List<string> arguments,
|
||||
IList<string> arguments,
|
||||
ServerPaths buildPaths,
|
||||
CancellationToken cancellationToken,
|
||||
string keepAlive = null,
|
||||
|
|
@ -107,7 +107,7 @@ namespace Microsoft.AspNetCore.Razor.Tools
|
|||
}
|
||||
|
||||
private static async Task<ServerResponse> RunOnServerCore(
|
||||
List<string> arguments,
|
||||
IList<string> arguments,
|
||||
ServerPaths buildPaths,
|
||||
string pipeName,
|
||||
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.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
|
||||
{
|
||||
private readonly string _projectName;
|
||||
private readonly string _baseDirectory;
|
||||
private readonly string[] _additionalProjects;
|
||||
|
||||
public InitializeTestProjectAttribute(string projectName, params string[] additionalProjects)
|
||||
: this (projectName, string.Empty, additionalProjects)
|
||||
{
|
||||
}
|
||||
|
||||
public InitializeTestProjectAttribute(string projectName, string baseDirectory, string[] additionalProjects)
|
||||
{
|
||||
_projectName = projectName;
|
||||
_baseDirectory = baseDirectory;
|
||||
_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)}");
|
||||
}
|
||||
|
||||
MSBuildIntegrationTestBase.Project = ProjectDirectory.Create(_projectName, _additionalProjects);
|
||||
MSBuildIntegrationTestBase.Project = ProjectDirectory.Create(_projectName, _baseDirectory, _additionalProjects);
|
||||
}
|
||||
|
||||
public override void After(MethodInfo methodUnderTest)
|
||||
|
|
|
|||
|
|
@ -18,9 +18,9 @@ namespace Microsoft.AspNetCore.Razor.Design.IntegrationTests
|
|||
public bool PreserveWorkingDirectory { get; set; }
|
||||
#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);
|
||||
|
||||
try
|
||||
|
|
|
|||
Loading…
Reference in New Issue