Files
FSI.BT.IR.Tools/RoboSharp/JobFileBuilder.cs
Stephan Maier 647f938eee v1.2
2024-08-27 08:10:27 +02:00

587 lines
28 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
using System.IO;
using System.Text;
using System.Threading.Tasks;
using System.Text.RegularExpressions;
using System.Runtime.CompilerServices;
namespace RoboSharp
{
internal static class JobFileBuilder
{
#region < Constants & Regex >
/// <summary>
/// Any comments within the job file lines will start with this string
/// </summary>
public const string JOBFILE_CommentPrefix = ":: ";
/// <inheritdoc cref="JobFile.JOBFILE_Extension"/>
public const string JOBFILE_Extension = JobFile.JOBFILE_Extension;
/// <inheritdoc cref="JobFile.JOBFILE_Extension"/>
internal const string JOBFILE_JobName = ":: JOB_NAME: ";
internal const string JOBFILE_StopIfDisposing = ":: StopIfDisposing: ";
/// <summary>Pattern to Identify the SWITCH, DELIMITER and VALUE section</summary>
private const string RegString_SWITCH = "\\s*(?<SWITCH>\\/[A-Za-z]+[-]{0,1})(?<DELIMITER>\\s*:?\\s*)(?<VALUE>.+?)";
/// <summary>Pattern to Identify the SWITCH, DELIMIETER and VALUE section</summary>
private const string RegString_SWITCH_NumericValue = "\\s*(?<SWITCH>\\/[A-Za-z]+[-]{0,1})(?<DELIMITER>\\s*:?\\s*)(?<VALUE>[0-9]+?)";
/// <summary>Pattern to Identify COMMENT sections - Throws out white space and comment delimiter '::' </summary>
private const string RegString_COMMENT = "((?:\\s*[:]{2,}\\s*[:]{0,})(?<COMMENT>.*))";
/// <summary>
/// Regex to check if an entire line is a comment
/// </summary>
/// <remarks>
/// Captured Group Names: <br/>
/// COMMENT
/// </remarks>
private readonly static Regex LINE_IsComment = new Regex("^(?:\\s*[:]{2,}\\s*)(?<COMMENT>.*)$", RegexOptions.Compiled | RegexOptions.ExplicitCapture);
/// <summary>
/// Regex to check if the string is a flag for RoboCopy - These typically will have comments
/// </summary>
/// <remarks>
/// Captured Group Names: <br/>
/// SWITCH <br/>
/// DELIMITER <br/>
/// VALUE <br/>
/// COMMENT
/// </remarks>
private readonly static Regex LINE_IsSwitch = new Regex($"^{RegString_SWITCH}{RegString_COMMENT}$", RegexOptions.Compiled | RegexOptions.ExplicitCapture);
private readonly static Regex LINE_IsSwitch_NoComment = new Regex($"^{RegString_SWITCH}$", RegexOptions.Compiled | RegexOptions.ExplicitCapture);
private readonly static Regex LINE_IsSwitch_NumericValue = new Regex($"^{RegString_SWITCH_NumericValue}{RegString_COMMENT}$", RegexOptions.Compiled | RegexOptions.ExplicitCapture);
private readonly static Regex LINE_IsSwitch_NumericValue_NoComment = new Regex($"^{RegString_SWITCH_NumericValue}$", RegexOptions.Compiled | RegexOptions.ExplicitCapture);
/// <summary>
/// JobName for ROboCommand is not valid parameter for RoboCopy, so we save it into a comment within the file
/// </summary>
/// <remarks>
/// Captured Group Names: <br/>
/// FLAG <br/>
/// NAME <br/>
/// COMMENT
/// </remarks>
private readonly static Regex JobNameRegex = new Regex("^\\s*(?<FLAG>:: JOB_NAME:)\\s*(?<NAME>.*)", RegexOptions.Compiled | RegexOptions.ExplicitCapture);
private readonly static Regex StopIfDisposingRegex = new Regex("^\\s*(?<FLAG>:: StopIfDisposing:)\\s*(?<VALUE>TRUE|FALSE)", RegexOptions.Compiled | RegexOptions.ExplicitCapture);
/// <summary>
/// Regex used for parsing File and Directory filters for /IF /XD and /XF flags
/// </summary>
/// <remarks>
/// Captured Group Names: <br/>
/// PATH <br/>
/// COMMENT
/// </remarks>
private readonly static Regex DirFileFilterRegex = new Regex($"^\\s*{RegString_FileFilter}{RegString_COMMENT}$", RegexOptions.Compiled | RegexOptions.ExplicitCapture);
private readonly static Regex DirFileFilterRegex_NoComment = new Regex($"^\\s*{RegString_FileFilter}$", RegexOptions.Compiled | RegexOptions.ExplicitCapture);
private const string RegString_FileFilter = "(?<PATH>.+?)";
#region < Copy Options Regex >
/// <summary>
/// Regex to find the SourceDirectory within the JobFile
/// </summary>
/// <remarks>
/// Captured Group Names: <br/>
/// SWITCH <br/>
/// PATH <br/>
/// COMMENT
/// </remarks>
private readonly static Regex CopyOptionsRegex_SourceDir = new Regex("^\\s*(?<SWITCH>/SD:)(?<PATH>.*)(?<COMMENT>::.*)", RegexOptions.Compiled | RegexOptions.ExplicitCapture);
/// <summary>
/// Regex to find the DestinationDirectory within the JobFile
/// </summary>
/// <remarks>
/// Captured Group Names: <br/>
/// SWITCH <br/>
/// PATH <br/>
/// COMMENT
/// </remarks>
private readonly static Regex CopyOptionsRegex_DestinationDir = new Regex("^\\s*(?<SWITCH>/DD:)(?<PATH>.*)(?<COMMENT>::.*)", RegexOptions.Compiled | RegexOptions.ExplicitCapture);
/// <summary>
/// Regex to determine if on the INCLUDE FILES section of the JobFile
/// </summary>
/// <remarks>
/// Each new path / filename should be on its own line
/// </remarks>
private readonly static Regex CopyOptionsRegex_IncludeFiles = new Regex("^\\s*(?<SWITCH>/IF)\\s*(.*)", RegexOptions.Compiled | RegexOptions.ExplicitCapture);
#endregion
#region < Selection Options Regex >
/// <summary>
/// Regex to determine if on the EXCLUDE FILES section of the JobFile
/// </summary>
/// <remarks>
/// Each new path / filename should be on its own line
/// </remarks>
private readonly static Regex SelectionRegex_ExcludeFiles = new Regex("^\\s*(?<SWITCH>/XF).*", RegexOptions.Compiled | RegexOptions.ExplicitCapture);
/// <summary>
/// Regex to determine if on the EXCLUDE DIRECTORIES section of the JobFile
/// </summary>
/// <remarks>
/// Each new path / filename should be on its own line
/// </remarks>
private readonly static Regex SelectionRegex_ExcludeDirs = new Regex("^\\s*(?<SWITCH>/XD).*", RegexOptions.Compiled | RegexOptions.ExplicitCapture);
#endregion
#endregion
#region < Methods that feed Main Parse Routine >
/// <summary>
/// Read each line using <see cref="FileInfo.OpenText"/> and attempt to produce a Job File. <para/>
/// If FileExtension != ".RCJ" -> returns null. Otherwise parses the file.
/// </summary>
/// <param name="file">FileInfo object for some Job File. File Path should end in .RCJ</param>
/// <returns></returns>
[MethodImpl(methodImplOptions: MethodImplOptions.AggressiveInlining)]
internal static RoboCommand Parse(FileInfo file)
{
if (file.Extension != JOBFILE_Extension) return null;
return Parse(file.OpenText());
}
/// <summary>
/// Use <see cref="File.OpenText(string)"/> to read all lines from the supplied file path. <para/>
/// If FileExtension != ".RCJ" -> returns null. Otherwise parses the file.
/// </summary>
/// <param name="path">File Path to some Job File. File Path should end in .RCJ</param>
/// <returns></returns>
[MethodImpl(methodImplOptions: MethodImplOptions.AggressiveInlining)]
internal static RoboCommand Parse(string path)
{
if (Path.GetExtension(path) != JOBFILE_Extension) return null;
return Parse(File.OpenText(path));
}
/// <summary>
/// Read each line from a StreamReader and attempt to produce a Job File.
/// </summary>
/// <param name="streamReader">StreamReader for a file stream that represents a Job File</param>
/// <returns></returns>
[MethodImpl(methodImplOptions: MethodImplOptions.AggressiveInlining)]
internal static RoboCommand Parse(StreamReader streamReader)
{
List<string> Lines = new List<string>();
using (streamReader)
{
while (!streamReader.EndOfStream)
Lines.Add(streamReader.ReadLine());
}
return Parse(Lines);
}
#endregion
#region <> Main Parse Routine >
/// <summary>
/// Parse each line in <paramref name="Lines"/>, and attempt to create a new JobFile object.
/// </summary>
/// <param name="Lines">String[] read from a JobFile</param>
/// <returns></returns>
internal static RoboCommand Parse(IEnumerable<string> Lines)
{
//Extract information from the Lines to quicken processing in *OptionsRegex classes
List<Group> Flags = new List<Group>();
List<GroupCollection> ValueFlags = new List<GroupCollection>();
RetryOptions retryOpt = new RetryOptions();
string JobName = null;
bool stopIfDisposing = true;
foreach (string ln in Lines)
{
if (ln.IsNullOrWhiteSpace() | ln.Trim() == "::")
{ }
else if (LINE_IsSwitch.IsMatch(ln) || LINE_IsSwitch_NoComment.IsMatch(ln))
{
var groups = LINE_IsSwitch.Match(ln).Groups;
//Check RetryOptions inline since it only has 4 properties to check against
if (groups["SWITCH"].Value == "/R" && LINE_IsSwitch_NumericValue.IsMatch(ln))
{
string val = LINE_IsSwitch_NumericValue.Match(ln).Groups["VALUE"].Value;
retryOpt.RetryCount = val.IsNullOrWhiteSpace() ? retryOpt.RetryCount : Convert.ToInt32(val);
}
else if (groups["SWITCH"].Value == "/W")
{
string val = LINE_IsSwitch_NumericValue.Match(ln).Groups["VALUE"].Value;
retryOpt.RetryWaitTime = val.IsNullOrWhiteSpace() ? retryOpt.RetryWaitTime : Convert.ToInt32(val);
}
else if (groups["SWITCH"].Value == "/REG")
{
retryOpt.SaveToRegistry = true;
}
else if (groups["SWITCH"].Value == "/TBD")
{
retryOpt.WaitForSharenames = true;
}
//All Other flags
else
{
Flags.Add(groups["SWITCH"]);
if (groups["DELIMITER"].Success)
ValueFlags.Add(groups);
}
}
else if (JobName == null && JobNameRegex.IsMatch(ln))
{
JobName = JobNameRegex.Match(ln).Groups["NAME"].Value.Trim();
}
else if (StopIfDisposingRegex.IsMatch(ln))
{
stopIfDisposing = Convert.ToBoolean(StopIfDisposingRegex.Match(ln).Groups["VALUE"].Value);
}
}
CopyOptions copyOpt = Build_CopyOptions(Flags, ValueFlags, Lines);
SelectionOptions selectionOpt = Build_SelectionOptions(Flags, ValueFlags, Lines);
LoggingOptions loggingOpt = Build_LoggingOptions(Flags, ValueFlags, Lines);
JobOptions jobOpt = Build_JobOptions(Flags, ValueFlags, Lines);
return new RoboCommand(JobName ?? "", StopIfDisposing: stopIfDisposing, source: null, destination: null, configuration: null,
copyOptions: copyOpt,
selectionOptions: selectionOpt,
retryOptions: retryOpt,
loggingOptions: loggingOpt,
jobOptions: jobOpt);
}
#endregion
#region < Copy Options >
/// <summary>
/// Parser to create CopyOptions object for JobFiles
/// </summary>
private static CopyOptions Build_CopyOptions(IEnumerable<Group> Flags, IEnumerable<GroupCollection> ValueFlags, IEnumerable<string> Lines)
{
var options = new CopyOptions();
//Bool Checks
options.CheckPerFile = Flags.Any(flag => flag.Success && flag.Value == CopyOptions.CHECK_PER_FILE.Trim());
options.CopyAll = Flags.Any(flag => flag.Success && flag.Value == CopyOptions.COPY_ALL.Trim());
options.CopyFilesWithSecurity = Flags.Any(flag => flag.Success && flag.Value == CopyOptions.COPY_FILES_WITH_SECURITY.Trim());
options.CopySubdirectories = Flags.Any(flag => flag.Success && flag.Value == CopyOptions.COPY_SUBDIRECTORIES.Trim());
options.CopySubdirectoriesIncludingEmpty = Flags.Any(flag => flag.Success && flag.Value == CopyOptions.COPY_SUBDIRECTORIES_INCLUDING_EMPTY.Trim());
options.CopySymbolicLink = Flags.Any(flag => flag.Success && flag.Value == CopyOptions.COPY_SYMBOLIC_LINK.Trim());
options.CreateDirectoryAndFileTree = Flags.Any(flag => flag.Success && flag.Value == CopyOptions.CREATE_DIRECTORY_AND_FILE_TREE.Trim());
options.DoNotCopyDirectoryInfo = Flags.Any(flag => flag.Success && flag.Value == CopyOptions.DO_NOT_COPY_DIRECTORY_INFO.Trim());
options.DoNotUseWindowsCopyOffload = Flags.Any(flag => flag.Success && flag.Value == CopyOptions.DO_NOT_USE_WINDOWS_COPY_OFFLOAD.Trim());
options.EnableBackupMode = Flags.Any(flag => flag.Success && flag.Value == CopyOptions.ENABLE_BACKUP_MODE.Trim());
options.EnableEfsRawMode = Flags.Any(flag => flag.Success && flag.Value == CopyOptions.ENABLE_EFSRAW_MODE.Trim());
options.EnableRestartMode = Flags.Any(flag => flag.Success && flag.Value == CopyOptions.ENABLE_RESTART_MODE.Trim());
options.EnableRestartModeWithBackupFallback = Flags.Any(flag => flag.Success && flag.Value == CopyOptions.ENABLE_RESTART_MODE_WITH_BACKUP_FALLBACK.Trim());
options.FatFiles = Flags.Any(flag => flag.Success && flag.Value == CopyOptions.FAT_FILES.Trim());
options.FixFileSecurityOnAllFiles = Flags.Any(flag => flag.Success && flag.Value == CopyOptions.FIX_FILE_SECURITY_ON_ALL_FILES.Trim());
options.FixFileTimesOnAllFiles = Flags.Any(flag => flag.Success && flag.Value == CopyOptions.FIX_FILE_TIMES_ON_ALL_FILES.Trim());
options.Mirror = Flags.Any(flag => flag.Success && flag.Value == CopyOptions.MIRROR.Trim());
options.MoveFiles = Flags.Any(flag => flag.Success && flag.Value == CopyOptions.MOVE_FILES.Trim());
options.MoveFilesAndDirectories = Flags.Any(flag => flag.Success && flag.Value == CopyOptions.MOVE_FILES_AND_DIRECTORIES.Trim());
options.Purge = Flags.Any(flag => flag.Success && flag.Value == CopyOptions.PURGE.Trim());
options.RemoveFileInformation = Flags.Any(flag => flag.Success && flag.Value == CopyOptions.REMOVE_FILE_INFORMATION.Trim());
options.TurnLongPathSupportOff = Flags.Any(flag => flag.Success && flag.Value == CopyOptions.TURN_LONG_PATH_SUPPORT_OFF.Trim());
options.UseUnbufferedIo = Flags.Any(flag => flag.Success && flag.Value == CopyOptions.USE_UNBUFFERED_IO.Trim());
//int / string values on same line as flag
foreach (var match in ValueFlags)
{
string flag = match["SWITCH"].Value.Trim();
string value = match["VALUE"].Value.Trim();
switch (flag)
{
case "/A+":
options.AddAttributes = value;
break;
case "/COPY":
options.CopyFlags = value;
break;
case "/LEV":
options.Depth = value.TryConvertInt();
break;
case "/DD":
options.Destination = value;
break;
case "/DCOPY":
options.DirectoryCopyFlags = value;
break;
case "/IPG":
options.InterPacketGap = value.TryConvertInt();
break;
case "/MON":
options.MonitorSourceChangesLimit = value.TryConvertInt();
break;
case "/MOT":
options.MonitorSourceTimeLimit = value.TryConvertInt();
break;
case "/MT":
options.MultiThreadedCopiesCount = value.TryConvertInt();
break;
case "/A-":
options.RemoveAttributes = value;
break;
case "/RH":
options.RunHours = value;
break;
case "/SD":
options.Source = value;
break;
}
}
//Multiple Lines
if (Flags.Any(f => f.Value == "/IF"))
{
bool parsingIF = false;
List<string> filters = new List<string>();
string path = null;
//Find the line that starts with the flag
foreach (string ln in Lines)
{
if (ln.IsNullOrWhiteSpace() || LINE_IsComment.IsMatch(ln))
{ }
else if (LINE_IsSwitch.IsMatch(ln))
{
if (parsingIF) break; //Moving onto next section -> IF already parsed.
parsingIF = ln.Trim().StartsWith("/IF");
}
else if (parsingIF)
{
//React to parsing the section - Comments are not expected on these lines
path = null;
if (DirFileFilterRegex.IsMatch(ln))
{
path = DirFileFilterRegex.Match(ln).Groups["PATH"].Value;
}
else if (DirFileFilterRegex_NoComment.IsMatch(ln))
{
path = DirFileFilterRegex_NoComment.Match(ln).Groups["PATH"].Value;
}
//Store the value
if (!path.IsNullOrWhiteSpace())
{
filters.Add(path.WrapPath());
}
}
}
if (filters.Count > 0) options.FileFilter = filters;
} //End of FileFilter section
return options;
}
#endregion
#region < Selection Options >
/// <summary>
/// Parser to create SelectionOptions object for JobFiles
/// </summary>
private static SelectionOptions Build_SelectionOptions(IEnumerable<Group> Flags, IEnumerable<GroupCollection> ValueFlags, IEnumerable<string> Lines)
{
var options = new SelectionOptions();
//Bool Checks
options.CompensateForDstDifference = Flags.Any(flag => flag.Success && flag.Value == SelectionOptions.COMPENSATE_FOR_DST_DIFFERENCE.Trim());
options.ExcludeChanged = Flags.Any(flag => flag.Success && flag.Value == SelectionOptions.EXCLUDE_CHANGED.Trim());
options.ExcludeExtra = Flags.Any(flag => flag.Success && flag.Value == SelectionOptions.EXCLUDE_EXTRA.Trim());
options.ExcludeJunctionPoints = Flags.Any(flag => flag.Success && flag.Value == SelectionOptions.EXCLUDE_JUNCTION_POINTS.Trim());
options.ExcludeJunctionPointsForDirectories = Flags.Any(flag => flag.Success && flag.Value == SelectionOptions.EXCLUDE_JUNCTION_POINTS_FOR_DIRECTORIES.Trim());
options.ExcludeJunctionPointsForFiles = Flags.Any(flag => flag.Success && flag.Value == SelectionOptions.EXCLUDE_JUNCTION_POINTS_FOR_FILES.Trim());
options.ExcludeLonely = Flags.Any(flag => flag.Success && flag.Value == SelectionOptions.EXCLUDE_LONELY.Trim());
options.ExcludeNewer = Flags.Any(flag => flag.Success && flag.Value == SelectionOptions.EXCLUDE_NEWER.Trim());
options.ExcludeOlder = Flags.Any(flag => flag.Success && flag.Value == SelectionOptions.EXCLUDE_OLDER.Trim());
options.IncludeSame = Flags.Any(flag => flag.Success && flag.Value == SelectionOptions.INCLUDE_SAME.Trim());
options.IncludeTweaked = Flags.Any(flag => flag.Success && flag.Value == SelectionOptions.INCLUDE_TWEAKED.Trim());
options.OnlyCopyArchiveFiles = Flags.Any(flag => flag.Success && flag.Value == SelectionOptions.ONLY_COPY_ARCHIVE_FILES.Trim());
options.OnlyCopyArchiveFilesAndResetArchiveFlag = Flags.Any(flag => flag.Success && flag.Value == SelectionOptions.ONLY_COPY_ARCHIVE_FILES_AND_RESET_ARCHIVE_FLAG.Trim());
options.UseFatFileTimes = Flags.Any(flag => flag.Success && flag.Value == SelectionOptions.USE_FAT_FILE_TIMES.Trim());
//int / string values on same line as flag
foreach (var match in ValueFlags)
{
string flag = match["SWITCH"].Value;
string value = match["VALUE"].Value;
switch (flag)
{
case "/XA":
options.ExcludeAttributes = value;
break;
case "/IA":
options.IncludeAttributes = value;
break;
case "/MAXAGE":
options.MaxFileAge = value;
break;
case "/MAX":
options.MaxFileSize = value.TryConvertLong();
break;
case "/MAXLAD":
options.MaxLastAccessDate = value;
break;
case "/MINAGE":
options.MinFileAge = value;
break;
case "/MIN":
options.MinFileSize = value.TryConvertLong();
break;
case "/MINLAD":
options.MinLastAccessDate = value;
break;
}
}
//Multiple Lines
bool parsingXD = false;
bool parsingXF = false;
bool xDParsed = false;
bool xFParsed = false;
string path = null;
foreach (string ln in Lines)
{
// Determine if parsing some section
if (ln.IsNullOrWhiteSpace() || LINE_IsComment.IsMatch(ln) )
{ }
else if (!xFParsed && !parsingXF && SelectionRegex_ExcludeFiles.IsMatch(ln))
{
// Paths are not expected to be on this output line
parsingXF = true;
parsingXD = false;
}
else if (!xDParsed && !parsingXD && SelectionRegex_ExcludeDirs.IsMatch(ln))
{
// Paths are not expected to be on this output line
parsingXF = false;
parsingXD = true;
}
else if (LINE_IsSwitch.IsMatch(ln) || LINE_IsSwitch_NoComment.IsMatch(ln))
{
if (parsingXD)
{
parsingXD = false;
xDParsed = true;
}
if (parsingXF)
{
parsingXF = false;
xFParsed = true;
}
if (xDParsed && xFParsed) break;
}
else
{
//React to parsing the section - Comments are not expected on these lines
path = null;
if (DirFileFilterRegex.IsMatch(ln))
{
path = DirFileFilterRegex.Match(ln).Groups["PATH"].Value;
}
else if (DirFileFilterRegex_NoComment.IsMatch(ln))
{
path = DirFileFilterRegex_NoComment.Match(ln).Groups["PATH"].Value;
}
//Store the value
if (!path.IsNullOrWhiteSpace())
{
if (parsingXF)
options.ExcludedFiles.Add(path.WrapPath());
else if (parsingXD)
options.ExcludedDirectories.Add(path.WrapPath());
}
}
}
return options;
}
#endregion
#region < Logging Options >
/// <summary>
/// Parser to create LoggingOptions object for JobFiles
/// </summary>
private static LoggingOptions Build_LoggingOptions(IEnumerable<Group> Flags, IEnumerable<GroupCollection> ValueFlags, IEnumerable<string> Lines)
{
var options = new LoggingOptions();
//Bool Checks
options.IncludeFullPathNames = Flags.Any(flag => flag.Success && flag.Value == LoggingOptions.INCLUDE_FULL_PATH_NAMES.Trim());
options.IncludeSourceTimeStamps = Flags.Any(flag => flag.Success && flag.Value == LoggingOptions.INCLUDE_SOURCE_TIMESTAMPS.Trim());
options.ListOnly = Flags.Any(flag => flag.Success && flag.Value == LoggingOptions.LIST_ONLY.Trim());
options.NoDirectoryList = Flags.Any(flag => flag.Success && flag.Value == LoggingOptions.NO_DIRECTORY_LIST.Trim());
options.NoFileClasses = Flags.Any(flag => flag.Success && flag.Value == LoggingOptions.NO_FILE_CLASSES.Trim());
options.NoFileList = Flags.Any(flag => flag.Success && flag.Value == LoggingOptions.NO_FILE_LIST.Trim());
options.NoFileSizes = Flags.Any(flag => flag.Success && flag.Value == LoggingOptions.NO_FILE_SIZES.Trim());
options.NoJobHeader = Flags.Any(flag => flag.Success && flag.Value == LoggingOptions.NO_JOB_HEADER.Trim());
options.NoJobSummary = Flags.Any(flag => flag.Success && flag.Value == LoggingOptions.NO_JOB_SUMMARY.Trim());
options.NoProgress = Flags.Any(flag => flag.Success && flag.Value == LoggingOptions.NO_PROGRESS.Trim());
options.OutputAsUnicode = Flags.Any(flag => flag.Success && flag.Value == LoggingOptions.OUTPUT_AS_UNICODE.Trim());
options.OutputToRoboSharpAndLog = Flags.Any(flag => flag.Success && flag.Value == LoggingOptions.OUTPUT_TO_ROBOSHARP_AND_LOG.Trim());
options.PrintSizesAsBytes = Flags.Any(flag => flag.Success && flag.Value == LoggingOptions.PRINT_SIZES_AS_BYTES.Trim());
options.ReportExtraFiles = Flags.Any(flag => flag.Success && flag.Value == LoggingOptions.REPORT_EXTRA_FILES.Trim());
options.ShowEstimatedTimeOfArrival = Flags.Any(flag => flag.Success && flag.Value == LoggingOptions.SHOW_ESTIMATED_TIME_OF_ARRIVAL.Trim());
options.VerboseOutput = Flags.Any(flag => flag.Success && flag.Value == LoggingOptions.VERBOSE_OUTPUT.Trim());
//int / string values on same line as flag
foreach (var match in ValueFlags)
{
string flag = match["SWITCH"].Value;
string value = match["VALUE"].Value;
switch (flag)
{
case "/LOG+":
options.AppendLogPath = value;
break;
case "/UNILOG+":
options.AppendUnicodeLogPath = value;
break;
case "/LOG":
options.LogPath = value;
break;
case "/UNILOG":
options.UnicodeLogPath = value;
break;
}
}
return options;
}
#endregion
#region < Job Options >
/// <summary>
/// Parser to create JobOptions object for JobFiles
/// </summary>
private static JobOptions Build_JobOptions(IEnumerable<Group> Flags, IEnumerable<GroupCollection> ValueFlags, IEnumerable<string> Lines)
{
return new JobOptions();
}
#endregion
}
}