8000 Standalone implementation of a command line escape logic. · dotnet-script/dotnet-script@467eafd · GitHub
[go: up one dir, main page]

Skip to content

Commit 467eafd

Browse files
committed
Standalone implementation of a command line escape logic.
1 parent 818d495 commit 467eafd

File tree

4 files changed

+95
-4
lines changed

4 files changed

+95
-4
lines changed

src/Dotnet.Script.DependencyModel/Context/DotnetRestorer.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
using Dotnet.Script.DependencyModel.Environment;
2+
using Dotnet.Script.DependencyModel.Internal;
23
using Dotnet.Script.DependencyModel.Logging;
34
using Dotnet.Script.DependencyModel.Process;
45
using Dotnet.Script.DependencyModel.ProjectSystem;
5-
using Gapotchenko.FX.Diagnostics;
66
using System;
77
using System.IO;
88
using System.Linq;

src/Dotnet.Script.DependencyModel/Dotnet.Script.DependencyModel.csproj

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,6 @@
3232
</ItemGroup>
3333

3434
<ItemGroup>
35-
<PackageReference Include="Gapotchenko.FX.Diagnostics.CommandLine" Version="2021.1.5" />
3635
<PackageReference Include="NuGet.ProjectModel" Version="5.2.0" />
3736
<PackageReference Include="Microsoft.DotNet.PlatformAbstractions" Version="3.1.6" />
3837
</ItemGroup>
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
using System;
2+
using System.Text;
3+
using System.Text.RegularExpressions;
4+
5+
namespace Dotnet.Script.DependencyModel.Internal
6+
{
7+
/// <summary>
8+
/// <para>
9+
/// Performs operations on <see cref="System.String"/> instances that contain command line information.
10+
/// </para>
11+
/// <para>
12+
/// Tip: a ready-to-use package with this functionality is available at https://www.nuget.org/packages/Gapotchenko.FX.Diagnostics.CommandLine.
13+
/// </para>
14+
/// </summary>
15+
/// <summary>
16+
/// Available
17+
/// </summary>
18+
static class CommandLine
19+
{
20+
/// <summary>
21+
/// Escapes and optionally quotes a command line argument.
22+
/// </summary>
23+
/// <param name="value">The command line argument.</param>
24+
/// <returns>The escaped and optionally quoted command line argument.</returns>
25+
public static string EscapeArgument(string value)
26+
{
27+
if (value == null)
28+
return null;
29+
30+
int length = value.Length;
31+
if (length == 0)
32+
return string.Empty;
33+
34+
var sb = new StringBuilder();
35+
Escape.AppendQuotedText(sb, value);
36+
37+
if (sb.Length == length)
38+
return value;
39+
40+
return sb.ToString();
41+
}
42+
43+
static class Escape
44+
{
45+
public static void AppendQuotedText(StringBuilder sb, string text)
46+
{
47+
bool quotingRequired = IsQuotingRequired(text);
48+
if (quotingRequired)
49+
sb.Append('"');
50+
51+
int numberOfQuotes = 0;
52+
for (int i = 0; i < text.Length; i++)
53+
{
54+
if (text[i] == '"')
55+
numberOfQuotes++;
56+
}
57+
58+
if (numberOfQuotes > 0)
59+
{
60+
if ((numberOfQuotes % 2) != 0)
61+
throw new Exception("Command line parameter cannot contain an odd number of double quotes.");
62+
text = text.Replace("\\\"", "\\\\\"").Replace("\"", "\\\"");
63+
}
64+
65+
sb.Append(text);
66+
67+
if (quotingRequired && text.EndsWith("\\"))
68+
sb.Append('\\');
69+
70+
if (quotingRequired)
71+
sb.Append('"');
72+
}
73+
74+
static bool IsQuotingRequired(string parameter) =>
75+
!AllowedUnquotedRegex.IsMatch(parameter) ||
76+
DefinitelyNeedQuotesRegex.IsMatch(parameter);
77+
78+
static Regex m_CachedAllowedUnquotedRegex;
79+
80+
static Regex AllowedUnquotedRegex =>
81+
m_CachedAllowedUnquotedRegex ??= new Regex(
82+
@"^[a-z\\/:0-9\._\-+=]*$",
83+
RegexOptions.IgnoreCase | RegexOptions.CultureInvariant);
84+
85+
static Regex m_CachedDefinitelyNeedQuotesRegex;
86+
87+
static Regex DefinitelyNeedQuotesRegex =>
88+
m_CachedDefinitelyNeedQuotesRegex ??= new Regex(
89+
"[|><\\s,;\"]+",
90+
RegexOptions.CultureInvariant);
91+
}
92+
}
93+
}

src/Dotnet.Script.Tests/ScriptExecutionTests.cs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
using System.Text;
44
using Dotnet.Script.DependencyModel.Environment;
55
using Dotnet.Script.Shared.Tests;
6-
using Gapotchenko.FX.Diagnostics;
76
using Xunit;
87
using Xunit.Abstractions;
98

@@ -140,7 +139,7 @@ public void ShouldHandleIssue181()
140139
[Fact]
141140
public void ShouldHandleIssue189()
142141
{
143-
var result = ScriptTestRunner.Default.Execute(CommandLine.Build(Path.Combine(TestPathUtils.GetPathToTestFixtureFolder("Issue189"), "SomeFolder", "Script.csx")));
142+
var result = ScriptTestRunner.Default.Execute($"\"{Path.Combine(TestPathUtils.GetPathToTestFixtureFolder("Issue189"), "SomeFolder", "Script.csx")}\"");
144143
Assert.Contains("Newtonsoft.Json.JsonConvert", result.output);
145144
}
146145

0 commit comments

Comments
 (0)
0