public IPatch ExtractPatch(UrlDir.UrlConfig urlConfig) { if (urlConfig == null) { throw new ArgumentNullException(nameof(urlConfig)); } try { if (!urlConfig.type.IsBracketBalanced()) { progress.Error(urlConfig, "Error - node name does not have balanced brackets (or a space - if so replace with ?):\n" + urlConfig.SafeUrl()); return(null); } Command command = CommandParser.Parse(urlConfig.type, out string name); if (command == Command.Replace) { progress.Error(urlConfig, $"Error - replace command (%) is not valid on a root node: {urlConfig.SafeUrl()}"); return(null); } else if (command == Command.Create) { progress.Error(urlConfig, $"Error - create command (&) is not valid on a root node: {urlConfig.SafeUrl()}"); return(null); } else if (command == Command.Rename) { progress.Error(urlConfig, $"Error - rename command (|) is not valid on a root node: {urlConfig.SafeUrl()}"); return(null); } else if (command == Command.Paste) { progress.Error(urlConfig, $"Error - paste command (#) is not valid on a root node: {urlConfig.SafeUrl()}"); return(null); } else if (command == Command.Special) { progress.Error(urlConfig, $"Error - special command (*) is not valid on a root node: {urlConfig.SafeUrl()}"); return(null); } ITagList tagList; try { tagList = tagListParser.Parse(name, urlConfig); } catch (FormatException ex) { progress.Error(urlConfig, $"Cannot parse node name as tag list: {ex.Message}\non: {urlConfig.SafeUrl()}"); return(null); } ProtoPatch protoPatch = protoPatchBuilder.Build(urlConfig, command, tagList); if (protoPatch == null) { return(null); } if (protoPatch.needs != null && !needsChecker.CheckNeedsExpression(protoPatch.needs)) { progress.NeedsUnsatisfiedRoot(urlConfig); return(null); } else if (!protoPatch.passSpecifier.CheckNeeds(needsChecker, progress)) { return(null); } needsChecker.CheckNeedsRecursive(urlConfig.config, urlConfig); return(patchCompiler.CompilePatch(protoPatch)); } catch (Exception e) { progress.Exception(urlConfig, $"Exception while attempting to create patch from config: {urlConfig.SafeUrl()}", e); return(null); } }
public static void CheckNeeds(UrlDir gameDatabaseRoot, IEnumerable <string> mods, IPatchProgress progress, IBasicLogger logger) { UrlDir gameData = gameDatabaseRoot.children.First(dir => dir.type == UrlDir.DirectoryType.GameData && dir.name == ""); foreach (UrlDir.UrlConfig mod in gameDatabaseRoot.AllConfigs.ToArray()) { UrlDir.UrlConfig currentMod = mod; try { if (mod.config.name == null) { progress.Error(currentMod, "Error - Node in file " + currentMod.parent.url + " subnode: " + currentMod.type + " has config.name == null"); } UrlDir.UrlConfig newMod; if (currentMod.type.IndexOf(":NEEDS[", StringComparison.OrdinalIgnoreCase) >= 0) { string type = currentMod.type; if (CheckNeeds(ref type, mods, gameData)) { ConfigNode copy = new ConfigNode(type); copy.ShallowCopyFrom(currentMod.config); int index = mod.parent.configs.IndexOf(currentMod); newMod = new UrlDir.UrlConfig(currentMod.parent, copy); mod.parent.configs[index] = newMod; } else { progress.NeedsUnsatisfiedRoot(currentMod); mod.parent.configs.Remove(currentMod); continue; } } else { newMod = currentMod; } // Recursively check the contents PatchContext context = new PatchContext(newMod, gameDatabaseRoot, logger, progress); CheckNeeds(new NodeStack(newMod.config), context, mods, gameData); } catch (Exception ex) { try { mod.parent.configs.Remove(currentMod); } catch (Exception ex2) { logger.Exception("Exception while attempting to ensure config removed", ex2); } try { progress.Exception(mod, "Exception while checking needs on root node :\n" + mod.PrettyPrint(), ex); } catch (Exception ex2) { progress.Exception("Exception while attempting to log an exception", ex2); } } } }