// Copyright Epic Games, Inc. All Rights Reserved.
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
using Tools.DotNETCommon;
namespace BuildAgent
{
class Program
{
///
/// Entry point
///
/// Command-line arguments
/// Exit code
static int Main(string[] Args)
{
try
{
Log.TraceInformation("Welcome to the Danger Zone!");
int Result = GuardedMain(Args);
return Result;
}
catch (FatalErrorException Ex)
{
Log.WriteException(Ex, null);
return Ex.ExitCode;
}
catch (Exception Ex)
{
Log.WriteException(Ex, null);
return 1;
}
}
///
/// Actual Main function, without exception guards
///
/// Command-line arguments
/// Exit code
static int GuardedMain(string[] Args)
{
// Find the index of the first command
int ModeIndex = 0;
while (ModeIndex < Args.Length && Args[ModeIndex].StartsWith("-"))
{
ModeIndex++;
}
// Find all the ToolMode types
Dictionary ModeNameToType = new Dictionary(StringComparer.OrdinalIgnoreCase);
foreach (Type Type in Assembly.GetExecutingAssembly().GetTypes())
{
ProgramModeAttribute Attribute = Type.GetCustomAttribute();
if (Attribute != null)
{
ModeNameToType.Add(Attribute.Name, Type);
}
}
// Check if there are any commands specified on the command line.
if (ModeIndex == Args.Length)
{
Log.TraceInformation("BuildAgent");
Log.TraceInformation("");
Log.TraceInformation("Utility for managing automated processes on build machines.");
Log.TraceInformation("");
Log.TraceInformation("Usage:");
Log.TraceInformation(" BuildAgent.exe [Command] [-Option1] [-Option2]...");
Log.TraceInformation("");
Log.TraceInformation("Commands:");
PrintCommands(ModeNameToType);
Log.TraceInformation("");
Log.TraceInformation("Specify \"Command -Help\" for command-specific help");
return 0;
}
// Get the command name
string ModeName = Args[ModeIndex];
// Get the command type
Type ModeType;
if (!ModeNameToType.TryGetValue(ModeName, out ModeType))
{
Log.TraceError("Unknown command '{0}'.", ModeName);
Log.TraceInformation("");
Log.TraceInformation("Available commands");
PrintCommands(ModeNameToType);
return 1;
}
// Update the mode name to use the correct casing, in case we need it for error messages
ModeName = ModeType.GetCustomAttribute().Name;
// Build an argument list for the command, including all the global arguments as well as arguments until the next command
List ArgumentList = new List();
for (int Idx = 0; Idx < Args.Length; Idx++)
{
if (Idx != ModeIndex)
{
ArgumentList.Add(Args[Idx]);
}
}
CommandLineArguments ModeArguments = new CommandLineArguments(ArgumentList.ToArray());
// Create the command instance
ProgramMode Mode = (ProgramMode)Activator.CreateInstance(ModeType);
// If the help flag is specified, print the help info and exit immediately
if (ModeArguments.HasOption("-Help"))
{
HelpUtils.PrintHelp(ModeName, HelpUtils.GetDescription(ModeType), Mode.GetParameters(ModeArguments));
return 1;
}
// Configure the command
try
{
Mode.Configure(ModeArguments);
ModeArguments.CheckAllArgumentsUsed();
}
catch (CommandLineArgumentException Ex)
{
Log.TraceError("{0}: {1}", ModeName, Ex.Message);
Log.TraceInformation("");
Log.TraceInformation("Arguments for {0}:", ModeName);
HelpUtils.PrintTable(Mode.GetParameters(ModeArguments), 4, 24);
return 1;
}
// Execute all the commands
return Mode.Execute();
}
///
/// Print a formatted list of all the available commands
///
/// Map from command name to type
static void PrintCommands(Dictionary ModeNameToType)
{
List> Commands = new List>();
foreach (KeyValuePair Pair in ModeNameToType.OrderBy(x => x.Key))
{
ProgramModeAttribute Attribute = Pair.Value.GetCustomAttribute();
Commands.Add(new KeyValuePair(Attribute.Name, Attribute.Description));
}
HelpUtils.PrintTable(Commands, 4, 20);
}
}
}