using Semmle.Util;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Xml;
namespace Semmle.Autobuild
{
///
/// Wrapper around system calls so that the build scripts can be unit-tested.
///
public interface IBuildActions
{
///
/// Runs a process and captures its output.
///
/// The exe to run.
/// The other command line arguments.
/// The working directory (null for current directory).
/// Additional environment variables.
/// The lines of stdout.
/// The process exit code.
int RunProcess(string exe, string args, string workingDirectory, IDictionary env, out IList stdOut);
///
/// Runs a process but does not capture its output.
///
/// The exe to run.
/// The other command line arguments.
/// The working directory (null for current directory).
/// Additional environment variables.
/// The process exit code.
int RunProcess(string exe, string args, string workingDirectory, IDictionary env);
///
/// Tests whether a file exists, File.Exists().
///
/// The filename.
/// True iff the file exists.
bool FileExists(string file);
///
/// Tests whether a directory exists, Directory.Exists().
///
/// The directory name.
/// True iff the directory exists.
bool DirectoryExists(string dir);
///
/// Deletes a file, File.Delete().
///
/// The filename.
void FileDelete(string file);
///
/// Deletes a directory, Directory.Delete().
///
void DirectoryDelete(string dir, bool recursive);
///
/// Gets an environment variable, Environment.GetEnvironmentVariable().
///
/// The name of the variable.
/// The string value, or null if the variable is not defined.
string GetEnvironmentVariable(string name);
///
/// Gets the current directory, Directory.GetCurrentDirectory().
///
/// The current directory.
string GetCurrentDirectory();
///
/// Enumerates files in a directory, Directory.EnumerateFiles().
///
/// The directory to enumerate.
/// A list of filenames, or an empty list.
IEnumerable EnumerateFiles(string dir);
///
/// Enumerates the directories in a directory, Directory.EnumerateDirectories().
///
/// The directory to enumerate.
/// List of subdirectories, or empty list.
IEnumerable EnumerateDirectories(string dir);
///
/// True if we are running on Windows.
///
bool IsWindows();
///
/// Combine path segments, Path.Combine().
///
/// The parts of the path.
/// The combined path.
string PathCombine(params string[] parts);
///
/// Gets the full path for , Path.GetFullPath().
///
string GetFullPath(string path);
///
/// Writes contents to file, File.WriteAllText().
///
/// The filename.
/// The text.
void WriteAllText(string filename, string contents);
///
/// Loads the XML document from .
///
XmlDocument LoadXml(string filename);
///
/// Expand all Windows-style environment variables in ,
/// Environment.ExpandEnvironmentVariables()
///
string EnvironmentExpandEnvironmentVariables(string s);
}
///
/// An implementation of IBuildActions that actually performs the requested operations.
///
class SystemBuildActions : IBuildActions
{
void IBuildActions.FileDelete(string file) => File.Delete(file);
bool IBuildActions.FileExists(string file) => File.Exists(file);
ProcessStartInfo GetProcessStartInfo(string exe, string arguments, string workingDirectory, IDictionary environment, bool redirectStandardOutput)
{
var pi = new ProcessStartInfo(exe, arguments)
{
UseShellExecute = false,
RedirectStandardOutput = redirectStandardOutput
};
if (workingDirectory != null)
pi.WorkingDirectory = workingDirectory;
// Environment variables can only be used when not redirecting stdout
if (!redirectStandardOutput)
{
pi.Environment["UseSharedCompilation"] = "false";
if (environment != null)
environment.ForEach(kvp => pi.Environment[kvp.Key] = kvp.Value);
}
return pi;
}
int IBuildActions.RunProcess(string cmd, string args, string workingDirectory, IDictionary environment)
{
var pi = GetProcessStartInfo(cmd, args, workingDirectory, environment, false);
using (var p = Process.Start(pi))
{
p.WaitForExit();
return p.ExitCode;
}
}
int IBuildActions.RunProcess(string cmd, string args, string workingDirectory, IDictionary environment, out IList stdOut)
{
var pi = GetProcessStartInfo(cmd, args, workingDirectory, environment, true);
return pi.ReadOutput(out stdOut);
}
void IBuildActions.DirectoryDelete(string dir, bool recursive) => Directory.Delete(dir, recursive);
bool IBuildActions.DirectoryExists(string dir) => Directory.Exists(dir);
string IBuildActions.GetEnvironmentVariable(string name) => Environment.GetEnvironmentVariable(name);
string IBuildActions.GetCurrentDirectory() => Directory.GetCurrentDirectory();
IEnumerable IBuildActions.EnumerateFiles(string dir) => Directory.EnumerateFiles(dir);
IEnumerable IBuildActions.EnumerateDirectories(string dir) => Directory.EnumerateDirectories(dir);
bool IBuildActions.IsWindows() => Win32.IsWindows();
string IBuildActions.PathCombine(params string[] parts) => Path.Combine(parts);
void IBuildActions.WriteAllText(string filename, string contents) => File.WriteAllText(filename, contents);
XmlDocument IBuildActions.LoadXml(string filename)
{
var ret = new XmlDocument();
ret.Load(filename);
return ret;
}
string IBuildActions.GetFullPath(string path) => Path.GetFullPath(path);
public string EnvironmentExpandEnvironmentVariables(string s) => Environment.ExpandEnvironmentVariables(s);
public static readonly IBuildActions Instance = new SystemBuildActions();
}
}