Skip to content

Commit e7db3f8

Browse files
committed
Handle pipe name with whitespace properly
1 parent 1c9208b commit e7db3f8

File tree

6 files changed

+69
-24
lines changed

6 files changed

+69
-24
lines changed

src/Microsoft.AspNetCore.Razor.Tools/Program.cs

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
33

44
using System;
5+
using System.IO;
56
using System.Threading;
67
using Microsoft.CodeAnalysis;
78

@@ -16,17 +17,34 @@ public static int Main(string[] args)
1617
var cancel = new CancellationTokenSource();
1718
Console.CancelKeyPress += (sender, e) => { cancel.Cancel(); };
1819

20+
var outputWriter = new StringWriter();
21+
var errorWriter = new StringWriter();
22+
1923
// Prevent shadow copying.
2024
var loader = new DefaultExtensionAssemblyLoader(baseDirectory: null);
21-
var checker = new DefaultExtensionDependencyChecker(loader, Console.Out, Console.Error);
25+
var checker = new DefaultExtensionDependencyChecker(loader, outputWriter, errorWriter);
2226

2327
var application = new Application(
2428
cancel.Token,
2529
loader,
2630
checker,
27-
(path, properties) => MetadataReference.CreateFromFile(path, properties));
31+
(path, properties) => MetadataReference.CreateFromFile(path, properties),
32+
outputWriter,
33+
errorWriter);
34+
35+
var result = application.Execute(args);
36+
37+
var output = outputWriter.ToString();
38+
var error = errorWriter.ToString();
39+
40+
outputWriter.Dispose();
41+
errorWriter.Dispose();
42+
43+
// This will no-op if server logging is not enabled.
44+
ServerLogger.Log(output);
45+
ServerLogger.Log(error);
2846

29-
return application.Execute(args);
47+
return result;
3048
}
3149
}
3250
}

src/Microsoft.AspNetCore.Razor.Tools/ServerProtocol/ServerConnection.cs

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
using System.Text;
1010
using System.Threading;
1111
using System.Threading.Tasks;
12+
using Microsoft.Extensions.CommandLineUtils;
1213

1314
namespace Microsoft.AspNetCore.Razor.Tools
1415
{
@@ -283,14 +284,20 @@ private static async Task<ServerResponse> TryProcessRequest(
283284
// Internal for testing.
284285
internal static bool TryCreateServerCore(string clientDir, string pipeName, out int? processId, bool debug = false)
285286
{
286-
string expectedPath;
287-
string processArguments;
288287
processId = null;
289288

290289
// The server should be in the same directory as the client
291290
var expectedCompilerPath = Path.Combine(clientDir, ServerName);
292-
expectedPath = Environment.GetEnvironmentVariable("DOTNET_HOST_PATH") ?? "dotnet";
293-
processArguments = $@"""{expectedCompilerPath}"" {(debug ? "--debug" : "")} server -p {pipeName}";
291+
var expectedPath = Environment.GetEnvironmentVariable("DOTNET_HOST_PATH") ?? "dotnet";
292+
var argumentList = new string[]
293+
{
294+
expectedCompilerPath,
295+
debug ? "--debug" : "",
296+
"server",
297+
"-p",
298+
pipeName
299+
};
300+
var processArguments = ArgumentEscaper.EscapeAndConcatenate(argumentList);
294301

295302
if (!File.Exists(expectedCompilerPath))
296303
{

src/Microsoft.AspNetCore.Razor.Tools/ServerProtocol/ServerLogger.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ static ServerLogger()
4646
// Otherwise, assume that the environment variable specifies the name of the log file.
4747
if (Directory.Exists(loggingFileName))
4848
{
49-
loggingFileName = Path.Combine(loggingFileName, $"server.{loggingFileName}.{GetCurrentProcessId()}.log");
49+
loggingFileName = Path.Combine(loggingFileName, $"razorserver.{GetCurrentProcessId()}.log");
5050
}
5151

5252
// Open allowing sharing. We allow multiple processes to log to the same file, so we use share mode to allow that.

test/Microsoft.AspNetCore.Razor.Design.Test/IntegrationTests/BuildServerIntegrationTest.cs

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -164,5 +164,34 @@ public async Task ManualServerShutdown_NoPipeName_ShutsDownServer()
164164
Assert.Equal(0, exitCode);
165165
Assert.Contains("shut down completed", output.ToString());
166166
}
167+
168+
[Fact]
169+
[InitializeTestProject("SimpleMvc")]
170+
public async Task Build_WithWhiteSpaceInPipeName_BuildsSuccessfully()
171+
{
172+
// Start the server
173+
var pipeName = "pipe with whitespace";
174+
var fixture = new BuildServerTestFixture(pipeName);
175+
176+
try
177+
{
178+
// Run a build
179+
var result = await DotnetMSBuild(
180+
"Build",
181+
"/p:_RazorForceBuildServer=true",
182+
buildServerPipeName: pipeName);
183+
184+
Assert.BuildPassed(result);
185+
Assert.FileExists(result, OutputPath, "SimpleMvc.dll");
186+
Assert.FileExists(result, OutputPath, "SimpleMvc.pdb");
187+
Assert.FileExists(result, OutputPath, "SimpleMvc.Views.dll");
188+
Assert.FileExists(result, OutputPath, "SimpleMvc.Views.pdb");
189+
}
190+
finally
191+
{
192+
// Shutdown the server
193+
fixture.Dispose();
194+
}
195+
}
167196
}
168197
}

test/Microsoft.AspNetCore.Razor.Design.Test/IntegrationTests/BuildServerTestFixture.cs

Lines changed: 6 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,13 @@ public class BuildServerTestFixture : IDisposable
1414
{
1515
private static readonly TimeSpan _defaultShutdownTimeout = TimeSpan.FromSeconds(60);
1616

17-
public BuildServerTestFixture()
17+
public BuildServerTestFixture() : this(Guid.NewGuid().ToString())
1818
{
19-
PipeName = Guid.NewGuid().ToString();
19+
}
20+
21+
internal BuildServerTestFixture(string pipeName)
22+
{
23+
PipeName = pipeName;
2024

2125
if (!ServerConnection.TryCreateServerCore(Environment.CurrentDirectory, PipeName, out var processId))
2226
{
@@ -54,18 +58,5 @@ public void Dispose()
5458
}
5559
}
5660
}
57-
58-
private static string RecursiveFind(string path, string start)
59-
{
60-
var test = Path.Combine(start, path);
61-
if (File.Exists(test))
62-
{
63-
return start;
64-
}
65-
else
66-
{
67-
return RecursiveFind(path, new DirectoryInfo(start).Parent.FullName);
68-
}
69-
}
7061
}
7162
}

test/Microsoft.AspNetCore.Razor.Design.Test/IntegrationTests/MSBuildIntegrationTestBase.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ internal Task<MSBuildResult> DotnetMSBuild(
7171

7272
if (!suppressBuildServer)
7373
{
74-
buildArgumentList.Add($"/p:_RazorBuildServerPipeName={buildServerPipeName ?? BuildServer.PipeName}");
74+
buildArgumentList.Add($@"/p:_RazorBuildServerPipeName=""{buildServerPipeName ?? BuildServer.PipeName}""");
7575
7676
// The build server will not be used in netcoreapp2.0 because PipeOptions.CurrentUserOnly is not available.
7777
// But we still want to make sure to run the tests on the server. So suppress that check.

0 commit comments

Comments
 (0)