xamarin-macios/msbuild/Xamarin.MacDev.Tasks.Core/CommandLineArgumentBuilder.cs

184 строки
4.1 KiB
C#
Исходник Обычный вид История

2016-04-21 16:40:25 +03:00
using System;
using System.Text;
using System.Collections.Generic;
Implement a different escaping/quoting algorithm for arguments to System.Diagnostics.Process. (#7177) * Implement a different escaping/quoting algorithm for arguments to System.Diagnostics.Process. mono changed how quotes should be escaped when passed to System.Diagnostic.Process, so we need to change accordingly. The main difference is that single quotes don't have to be escaped anymore. This solves problems like this: System.ComponentModel.Win32Exception : ApplicationName='nuget', CommandLine='restore '/Users/vsts/agent/2.158.0/work/1/s/tests/sampletester/bin/Debug/repositories/ios-samples/WorkingWithTables/Part 3 - Customizing a Table\'s appearance/3 - CellCustomTable/CellCustomTable.sln' -Verbosity detailed -SolutionDir '/Users/vsts/agent/2.158.0/work/1/s/tests/sampletester/bin/Debug/repositories/ios-samples/WorkingWithTables/Part 3 - Customizing a Table\'s appearance/3 - CellCustomTable'', CurrentDirectory='/Users/vsts/agent/2.158.0/work/1/s/tests/sampletester/bin/Debug/repositories', Native error= Cannot find the specified file at System.Diagnostics.Process.StartWithCreateProcess (System.Diagnostics.ProcessStartInfo startInfo) [0x0029f] in /Users/builder/jenkins/workspace/build-package-osx-mono/2019-08/external/bockbuild/builds/mono-x64/mcs/class/System/System.Diagnostics/Process.cs:778 ref: https://github.com/mono/mono/pull/15047 * Rework process arguments to pass arrays/lists around instead of quoted strings. And then only convert to a string at the very end when we create the Process instance. In the future there will be a ProcessStartInfo.ArgumentList property we can use to give the original array/list of arguments directly to the BCL so that we can avoid quoting at all. These changes gets us almost all the way there already (except that the ArgumentList property isn't available quite yet). We also have to bump to target framework version v4.7.2 from v4.5 in several places because of 'Array.Empty<T> ()' which is now used in more places. * Parse linker flags from LinkWith attributes. * [sampletester] Bump to v4.7.2 for Array.Empty<T> (). * Fix typo. * Rename GetVerbosity -> AddVerbosity. * Remove unnecessary string interpolation. * Remove unused variable. * [mtouch] Simplify code a bit. * Use implicitly typed arrays.
2019-10-14 17:18:46 +03:00
using Xamarin.Utils;
2016-04-21 16:40:25 +03:00
namespace Xamarin.MacDev
{
/// <summary>
/// Builds a process argument string.
/// </summary>
public class CommandLineArgumentBuilder
2016-04-21 16:40:25 +03:00
{
static readonly char[] QuoteSpecials = new char[] { ' ', '\\', '\'', '"', ',', ';' };
readonly HashSet<string> hash = new HashSet<string> ();
readonly StringBuilder builder = new StringBuilder ();
public string ProcessPath {
get; private set;
}
public CommandLineArgumentBuilder ()
2016-04-21 16:40:25 +03:00
{
}
public CommandLineArgumentBuilder (string processPath)
2016-04-21 16:40:25 +03:00
{
ProcessPath = processPath;
}
public int Length {
get { return builder.Length; }
}
/// <summary>
/// Adds an argument without escaping or quoting.
/// </summary>
public void Add (string argument, bool appendLine = false)
2016-04-21 16:40:25 +03:00
{
if (builder.Length > 0 && !appendLine)
2016-04-21 16:40:25 +03:00
builder.Append (' ');
builder.Append (argument);
if (appendLine)
builder.AppendLine ();
2016-04-21 16:40:25 +03:00
hash.Add (argument);
}
/// <summary>
/// Adds an argument without escaping or quoting and goes to the next line
/// </summary>
public void AddLine (string argument)
{
Add (argument, true);
}
2016-04-21 16:40:25 +03:00
/// <summary>
/// Adds multiple arguments without escaping or quoting.
/// </summary>
public void Add (params string[] args)
{
foreach (var a in args)
Add (a);
}
/// <summary>
/// Adds a formatted argument, quoting and escaping as necessary.
/// </summary>
public void AddQuotedFormat (string argumentFormat, params object[] values)
{
AddQuoted (string.Format (argumentFormat, values));
}
public void AddQuotedFormat (string argumentFormat, object val0)
{
AddQuoted (string.Format (argumentFormat, val0));
}
static void AppendQuoted (StringBuilder quoted, string text, bool appendLine = false)
2016-04-21 16:40:25 +03:00
{
if (text.IndexOfAny (QuoteSpecials) != -1) {
quoted.Append ("\"");
for (int i = 0; i < text.Length; i++) {
if (text[i] == '\\' || text[i] == '"')
quoted.Append ('\\');
quoted.Append (text[i]);
}
quoted.Append ("\"");
} else {
quoted.Append (text);
}
if (appendLine)
quoted.AppendLine ();
2016-04-21 16:40:25 +03:00
}
/// <summary>Adds an argument, quoting and escaping as necessary.</summary>
/// <remarks>The .NET process class does not support escaped
/// arguments, only quoted arguments with escaped quotes.</remarks>
public void AddQuoted (string argument, bool appendLine = false)
2016-04-21 16:40:25 +03:00
{
if (argument == null)
return;
if (builder.Length > 0 && !appendLine)
2016-04-21 16:40:25 +03:00
builder.Append (' ');
AppendQuoted (builder, argument, appendLine);
2016-04-21 16:40:25 +03:00
hash.Add (argument);
}
/// <summary>
/// Adds an argument, quoting, escaping as necessary, and goes to the next line
/// </summary>
public void AddQuotedLine (string argument)
{
AddQuoted (argument, true);
}
2016-04-21 16:40:25 +03:00
/// <summary>
/// Adds multiple arguments, quoting and escaping each as necessary.
/// </summary>
public void AddQuoted (params string[] args)
{
foreach (var a in args)
AddQuoted (a);
}
/// <summary>
/// Contains the specified argument.
/// </summary>
/// <param name="argument">Argument.</param>
public bool Contains (string argument)
{
return hash.Contains (argument);
}
/// <summary>Quotes a string, escaping if necessary.</summary>
/// <remarks>The .NET process class does not support escaped
/// arguments, only quoted arguments with escaped quotes.</remarks>
public static string Quote (string text)
{
var quoted = new StringBuilder ();
AppendQuoted (quoted, text);
return quoted.ToString ();
}
public override string ToString ()
{
return builder.ToString ();
}
static bool TryParse (string commandline, out string[] argv, out Exception ex)
{
Implement a different escaping/quoting algorithm for arguments to System.Diagnostics.Process. (#7177) * Implement a different escaping/quoting algorithm for arguments to System.Diagnostics.Process. mono changed how quotes should be escaped when passed to System.Diagnostic.Process, so we need to change accordingly. The main difference is that single quotes don't have to be escaped anymore. This solves problems like this: System.ComponentModel.Win32Exception : ApplicationName='nuget', CommandLine='restore '/Users/vsts/agent/2.158.0/work/1/s/tests/sampletester/bin/Debug/repositories/ios-samples/WorkingWithTables/Part 3 - Customizing a Table\'s appearance/3 - CellCustomTable/CellCustomTable.sln' -Verbosity detailed -SolutionDir '/Users/vsts/agent/2.158.0/work/1/s/tests/sampletester/bin/Debug/repositories/ios-samples/WorkingWithTables/Part 3 - Customizing a Table\'s appearance/3 - CellCustomTable'', CurrentDirectory='/Users/vsts/agent/2.158.0/work/1/s/tests/sampletester/bin/Debug/repositories', Native error= Cannot find the specified file at System.Diagnostics.Process.StartWithCreateProcess (System.Diagnostics.ProcessStartInfo startInfo) [0x0029f] in /Users/builder/jenkins/workspace/build-package-osx-mono/2019-08/external/bockbuild/builds/mono-x64/mcs/class/System/System.Diagnostics/Process.cs:778 ref: https://github.com/mono/mono/pull/15047 * Rework process arguments to pass arrays/lists around instead of quoted strings. And then only convert to a string at the very end when we create the Process instance. In the future there will be a ProcessStartInfo.ArgumentList property we can use to give the original array/list of arguments directly to the BCL so that we can avoid quoting at all. These changes gets us almost all the way there already (except that the ArgumentList property isn't available quite yet). We also have to bump to target framework version v4.7.2 from v4.5 in several places because of 'Array.Empty<T> ()' which is now used in more places. * Parse linker flags from LinkWith attributes. * [sampletester] Bump to v4.7.2 for Array.Empty<T> (). * Fix typo. * Rename GetVerbosity -> AddVerbosity. * Remove unnecessary string interpolation. * Remove unused variable. * [mtouch] Simplify code a bit. * Use implicitly typed arrays.
2019-10-14 17:18:46 +03:00
return StringUtils.TryParseArguments (commandline, out argv, out ex);
2016-04-21 16:40:25 +03:00
}
public static bool TryParse (string commandline, out string[] argv)
{
Exception ex;
return TryParse (commandline, out argv, out ex);
}
public static string[] Parse (string commandline)
{
string[] argv;
Exception ex;
if (!TryParse (commandline, out argv, out ex))
throw ex;
return argv;
}
}
}