|
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
using Microsoft.Build.Framework;
using Microsoft.Build.Utilities;
using System;
using System.IO;
using System.Text;
namespace Microsoft.DotNet.Build.Tasks
{
public class GenerateRunScript : Task
{
[Required]
public string[] SetCommands { get; set; }
[Required]
public string[] RunCommands { get; set; }
[Required]
public string TemplatePath { get; set; }
[Required]
public string OutputPath { get; set; }
public override bool Execute()
{
if (RunCommands.Length == 0)
{
Log.LogError("Please provide at least one test command to execute via the RunCommands property.");
return false;
}
if (!File.Exists(TemplatePath))
{
Log.LogError($"Runner script template {TemplatePath} was not found.");
return false;
}
string templateContent = File.ReadAllText(TemplatePath);
Directory.CreateDirectory(Path.GetDirectoryName(OutputPath));
Log.LogMessage($"Run commands = {string.Join(Environment.NewLine, RunCommands)}");
string extension = Path.GetExtension(Path.GetFileName(OutputPath)).ToLowerInvariant();
switch (extension)
{
case ".sh":
case ".cmd":
case ".bat":
WriteRunScript(templateContent, extension);
break;
default:
Log.LogError($"Generating runner scripts with extension '{extension}' is not supported.");
return false;
}
return true;
}
private void WriteRunScript(string templateContent, string extension)
{
bool isUnix = extension == ".sh";
string lineFeed = isUnix ? "\n" : "\r\n";
string[] newlineSeparator = new string[] { Environment.NewLine };
var setCommandsBuilder = new StringBuilder();
for (int i = 0; i < SetCommands.Length; i++)
{
string[] setCommandsSplit = SetCommands[i].Split(newlineSeparator, StringSplitOptions.None);
for (int j = 0; j < setCommandsSplit.Length; j++)
{
setCommandsBuilder.Append(setCommandsSplit[j]);
if ((j < setCommandsSplit.Length - 1) || (i < SetCommands.Length - 1))
{
setCommandsBuilder.Append(lineFeed);
}
}
}
templateContent = templateContent.Replace("[[SetCommands]]", setCommandsBuilder.ToString());
var runCommandsBuilder = new StringBuilder();
for (int i = 0; i < RunCommands.Length; i++)
{
string[] runCommandsSplit = RunCommands[i].Split(newlineSeparator, StringSplitOptions.None);
for (int j = 0; j < runCommandsSplit.Length; j++)
{
runCommandsBuilder.Append(runCommandsSplit[j]);
if ((j < runCommandsSplit.Length - 1) || (i < RunCommands.Length - 1))
{
runCommandsBuilder.Append(lineFeed);
}
}
}
templateContent = templateContent.Replace("[[RunCommands]]", runCommandsBuilder.ToString());
var setCommandEchoesBuilder = new StringBuilder();
foreach (string setCommand in SetCommands)
{
foreach (string setCommandOneLine in setCommand.Split(newlineSeparator, StringSplitOptions.None))
{
setCommandEchoesBuilder.Append($"echo {SanitizeEcho(setCommandOneLine,isUnix)}{lineFeed}");
}
}
templateContent = templateContent.Replace("[[SetCommandsEcho]]", setCommandEchoesBuilder.ToString());
var runCommandEchoesBuilder = new StringBuilder();
foreach (string runCommand in RunCommands)
{
foreach (string runCommandOneLine in runCommand.Split(newlineSeparator, StringSplitOptions.None))
{
runCommandEchoesBuilder.Append($"echo {SanitizeEcho(runCommandOneLine,isUnix)}{lineFeed}");
}
}
templateContent = templateContent.Replace("[[RunCommandsEcho]]", runCommandEchoesBuilder.ToString());
if (isUnix)
{
// Just in case any Windows EOLs have made it in by here, clean any up.
templateContent = templateContent.Replace("\r\n", "\n");
}
using (StreamWriter sw = new StreamWriter(new FileStream(OutputPath, FileMode.Create)))
{
sw.NewLine = lineFeed;
sw.Write(templateContent);
sw.WriteLine();
}
Log.LogMessage($"Wrote {extension} run script to {OutputPath}");
}
private static string SanitizeEcho(string command, bool isUnix){
// Escape backtick and question mark characters to avoid running commands instead of echo'ing them.
string sanitizedRunCommand = command.Replace("`", "\\`")
.Replace("?", "\\")
.Replace("\r","")
.Replace("\n"," ")
.Replace("&", "^&")
.Replace(">", "^>");
if (isUnix)
{
// Remove parentheses and quotes from echo command before wrapping it in quotes to avoid errors on Linux.
sanitizedRunCommand = "\"" + sanitizedRunCommand.Replace("\"", "")
.Replace("(", "")
.Replace(")", "") + "\"";
}
return sanitizedRunCommand;
}
}
}
|