protected void ParseDownloadUrl() { if (RepoUrlPath[0].Equals('/') || RepoUrlPath[0].Equals('\\')) { Logging.Debug("Removing extra slash from the start of the URL"); RepoUrlPath = RepoUrlPath.Substring(1); } AutomationMacro automationXmlRepoFilebaseEscapedMacro = Macros.Find(macro => macro.Name.Equals("automationRepoRoot")); if (automationXmlRepoFilebaseEscapedMacro == null) { throw new BadMemeException("This shouldn't happen. Like literally. Should. Not. Happen."); } if (AutomationSettings.UseLocalRunnerDatabase) { RepoUrlPath = RepoUrlPath.Replace('/', '\\'); fullFilepath = Path.Combine(Path.GetDirectoryName(AutomationSettings.LocalRunnerDatabaseRoot), RepoUrlPath); } else { if (RepoUrlPath.Contains("\\")) { Logging.Warning("The RepoUrlPath argument contains folder seperator chars, but should be http url slashes"); RepoUrlPath = RepoUrlPath.Replace('\\', '/'); } fullFilepath = automationXmlRepoFilebaseEscapedMacro.Value + RepoUrlPath; } Logging.Debug("Parsed RepoUrlPath to resolve to {0}", fullFilepath); }
protected override void ImportList() { Logging.Debug("Setting each parsed macro as local, overriding if other local macro exists"); List <AutomationMacro> macroList = objectList as List <AutomationMacro>; foreach (AutomationMacro macro in macroList) { macro.MacroType = MacroType.Local; //check if macro already exists AutomationMacro result = Macros.Find(mac => mac.Name.ToLower().Equals(macro.Name.ToLower())); if (result != null) { if (result.MacroType != MacroType.Local) { Logging.Error("The parsed macro {{{0}}} already exists in the current macro list as macro type {1}, and cannot be overridden.", result.Name, result.MacroType.ToString()); continue; } else { Logging.Info("The parsed macro {{{0}}} already exists in the current macro list as macro type {1} with value {2}, and will be over-ridden", result.Name, result.MacroType.ToString(), result.Value); result.Value = macro.Value; } } else { Logging.Info("Adding macro {{{0}}} with value '{1}'", macro.Name, macro.Value); Macros.Add(macro); } } }
public override void ProcessTaskResults() { AutomationMacro macro = Macros.Find(mac => mac.Name.Equals(MacroName)); if (macro != null) { throw new BadMemeException("you have made a mistake"); } }
public override void ProcessTaskResults() { AutomationMacro macro = Macros.Find(mac => mac.Name.Equals(MacroName)); if (ProcessTaskResultTrue(macro == null, "Could not find newly created macro in list")) { return; } }
public override async Task RunTask() { Logging.Debug("Checking for if macro {0} already exists", MacroName); AutomationMacro macro = Macros.Find(mac => mac.Name.Equals(MacroName)); if (macro != null) { Logging.Debug("Macro found, removing"); Macros.Remove(macro); } }
public override void ProcessMacros() { base.ProcessMacros(); //if the value contains the macro old_package_property_value, the user probably wants to use the old value as part of the new value //check if it exists first and delete AutomationMacro macro = Macros.Find(mac => mac.Name.Equals("old_package_property_value")); if (macro != null) { Macros.Remove(macro); } PropertyValue = ProcessMacro(nameof(PropertyValue), PropertyValue); }
public override async Task RunTask() { string valueToSave; if (property.PropertyType.IsValueType) { valueToSave = property.GetValue(targetPackage).ToString(); } else { object currentValue = property.GetValue(targetPackage); //to get type of array //https://stackoverflow.com/a/2085186/3128017 Type arrayType = currentValue.GetType().GetElementType(); if (!(arrayType.IsValueType || arrayType.Equals(typeof(string)))) { Logging.Error("The array requested does not hold value type objects"); propertyGot = false; return; } Array arrayObject = currentValue as Array; if (propertyIndex > arrayObject.Length || propertyIndex < 0) { Logging.Error("Index {0} is not valid for this property, valid options are 0 to {1}", propertyIndex, arrayObject.Length - 1); propertyGot = false; return; } object indexedArrayObjectValue = arrayObject.GetValue(propertyIndex); valueToSave = indexedArrayObjectValue.ToString(); } Logging.Info("Creating macro for package {0} (UID {1}) of property {2}", targetPackage.PackageName, targetPackage.UID, property.Name); Logging.Info("Macro name: {0}, Value: {1}", MacroSaveName, valueToSave); AutomationMacro macro = Macros.Find(mac => mac.Name.Equals(MacroSaveName)); if (macro != null) { Macros.Remove(macro); } Macros.Add(new AutomationMacro() { MacroType = MacroType.Local, Name = MacroSaveName, Value = valueToSave }); propertyGot = true; }
protected static void ProcessMacro(string argName, ref string arg, List <AutomationMacro> macros, int recursionLevel = 0) { string recursiveLevelString = string.Empty; if (recursionLevel > 0) { recursiveLevelString = string.Format("(recursive level {0})", recursionLevel); } Logging.Info(Logfiles.AutomationRunner, LogOptions.MethodName, "Processing arg '{0}' {1}", argName, recursiveLevelString); Logging.Debug(Logfiles.AutomationRunner, LogOptions.MethodName, "Before processing: '{0}'", arg); //run regex on the arg to get the type of replacement to do. if it's recursive, then we need to process the inner one first Match result = Regex.Match(arg, AutomationMacro.MacroReplaceRegex); if (!result.Success) { //check if any "{" exist at all Match startBracketsMatch = Regex.Match(arg, "{"); if (startBracketsMatch.Captures.Count > 0) { Match endBracketsMatch = Regex.Match(arg, "}"); Logging.Error(Logfiles.AutomationRunner, LogOptions.MethodName, "Macros were detected in the argument, but the syntax was incorrect. Most likely is the number of start and end brackets are unbalanced."); Logging.Error(Logfiles.AutomationRunner, LogOptions.None, "Examine the number of brackets starting and ending in the argument, and try again. For debug, here's what was parsed:"); Logging.Info(Logfiles.AutomationRunner, LogOptions.None, "Argument value: {0}", arg); Logging.Info(Logfiles.AutomationRunner, LogOptions.None, "Start brackets count: {0}", startBracketsMatch.Captures.Count); foreach (Capture capture in startBracketsMatch.Captures) { Logging.Info(Logfiles.AutomationRunner, LogOptions.None, "Capture location in string: {0}", capture.Index); } Logging.Info(Logfiles.AutomationRunner, LogOptions.None, "End brackets count: {0}", endBracketsMatch.Captures.Count); foreach (Capture capture in endBracketsMatch.Captures) { Logging.Info(Logfiles.AutomationRunner, LogOptions.None, "Capture location in string: {0}", capture.Index); } return; } Logging.Info(Logfiles.AutomationRunner, LogOptions.MethodName, "The argument {0} has no macros, continue", argName); return; } int inner1Count = result.Groups[AutomationMacro.RegexGroupInner1].Captures.Count; int inner2Count = result.Groups[AutomationMacro.RegexGroupInner2].Captures.Count; int inner3Count = result.Groups[AutomationMacro.RegexGroupInner3].Captures.Count; //verify that 2 and 3 have the same number if (inner2Count != inner3Count) { Logging.Error(Logfiles.AutomationRunner, LogOptions.MethodName, "Inner2Count ({0}) != Inner3Count ({1})! The macro engine is not designed for this!", inner2Count, inner3Count); throw new NotImplementedException("soon tm"); } else if (inner2Count > inner1Count) { int countDifference = inner2Count - inner1Count; //this means that the regex must recurse x levels (the difference) into the string to solve the inner values first Logging.Debug(Logfiles.AutomationRunner, LogOptions.None, "Inner2Count ({0}) > Inner1Count ({1}), required to recuse {2} levels to solve inner macros", inner2Count, inner1Count, countDifference); //use the matches of inner1 to send each section into the regex engine again int captureCount = 0; foreach (Capture capture in result.Groups[AutomationMacro.RegexGroupInner1].Captures) { string capturedValue = capture.Value; Logging.Debug(Logfiles.AutomationRunner, LogOptions.None, "Running regex on Inner1Count: {0}", capturedValue); //get a count of how many "{" characters exist in this string. If it's 1, then just run this string through and call it good //if it's more then 1, then need to parse out the extra level via a new greedy regex int numStarts = capturedValue.Count(ch_ => ch_.Equals('{')); if (numStarts > 1) { Logging.Debug(Logfiles.AutomationRunner, LogOptions.None, "This match is {0} level of brackets, split out the brackets before recursively processing", numStarts); //we need to use the new value as the 'starting value', as if it didn't have a macro around it. for example, consider: //name_{use_{date}_val}_thing //after we resolve {date}, it will become part of the name for {use_{date}_val}. //the way to do this is to treat {use_{date}_val} as a word by itself, i.e. 'use_{date}_val' Regex subRegex = new Regex(@"{.+}"); Match sectionMatch = subRegex.Match(capturedValue); //following the example above, we have the section {use_{date}_val} //strip off the brackets and send it through string splitValue = sectionMatch.Value; splitValue = splitValue.Remove(0, 1); splitValue = splitValue.Remove(splitValue.Length - 1, 1); //we now have 'use_{date}_val', send that through the macro engine string innerResult = ProcessMacro(string.Format("{0}_capture{1}_level{2}", argName, captureCount, countDifference), splitValue, macros); //use_the_date_val, if {date} = the_date. put the brackets back on innerResult = "{" + innerResult + "}"; //{use_the_date_val}, now do the final replace of that macro Regex replaceRegex2 = new Regex(sectionMatch.Value); capturedValue = replaceRegex2.Replace(capturedValue, innerResult, 1); } else if (numStarts == 0) { throw new BadMemeException("whoa. didn't see that coming."); } else { Logging.Debug(Logfiles.AutomationRunner, LogOptions.None, "This match is 1 level of brackets, perform direct recursive replacement"); } string processedValue = ProcessMacro(string.Format("{0}_capture{1}_level{2}", argName, captureCount, countDifference), capturedValue, macros); Regex replaceRegex = new Regex(capture.Value); arg = replaceRegex.Replace(arg, processedValue, 1); captureCount++; } } else { //macros are at the same level, we can just replace as we see them //use inner3 as the method to determine what's inside foreach (Capture capture in result.Groups[AutomationMacro.RegexGroupInner3].Captures) { if (string.IsNullOrEmpty(capture.Value)) { continue; } Logging.Debug(Logfiles.AutomationRunner, LogOptions.None, "Processing macro {0}, string location {1}, length {2}", capture.Value, capture.Index, capture.Length); AutomationMacro resultMacro = macros.Find(macro => macro.Name.Equals(capture.Value)); if (resultMacro == null) { if (!SpecialCaseIgnoreMacro.Contains(capture.Value)) { Logging.Warning(Logfiles.AutomationRunner, LogOptions.None, "The macro with name '{0}', does not exist, skipping. (Is this intended?)", capture.Value); } continue; } string macroValue = resultMacro.Value; Match recursiveCheck = Regex.Match(macroValue, AutomationMacro.MacroReplaceRegex); if (recursiveCheck.Success) { Logging.Debug("A macro was resolved to another macro, run the macro replacement code again"); string temp = macroValue; ProcessMacro(argName, ref temp, macros, recursionLevel + 1); macroValue = temp; } //perform a single replace on the specified location of the string //https://stackoverflow.com/a/6372134/3128017 Regex replaceRegex = new Regex("{" + capture.Value + "}"); arg = replaceRegex.Replace(arg, macroValue, 1); Logging.Debug(Logfiles.AutomationRunner, LogOptions.None, "A single replace was done on the argument. Result: {0}", arg); } } Logging.Debug(Logfiles.AutomationRunner, LogOptions.MethodName, "After processing: {0}", arg); }