Example #1
0
        public void Apply(UrlDir.UrlFile file, IPatchProgress progress, IBasicLogger logger)
        {
            if (file == null)
            {
                throw new ArgumentNullException(nameof(file));
            }
            if (progress == null)
            {
                throw new ArgumentNullException(nameof(progress));
            }
            if (logger == null)
            {
                throw new ArgumentNullException(nameof(logger));
            }

            PatchContext context = new PatchContext(UrlConfig, file.root, logger, progress);

            // Avoid checking the new configs we are creating
            int count = file.configs.Count;

            for (int i = 0; i < count; i++)
            {
                UrlDir.UrlConfig url = file.configs[i];
                try
                {
                    if (!NodeMatcher.IsMatch(url.config))
                    {
                        continue;
                    }

                    ConfigNode clone = MMPatchLoader.ModifyNode(new NodeStack(url.config), UrlConfig.config, context);
                    if (url.config.HasValue("name") && url.config.GetValue("name") == clone.GetValue("name"))
                    {
                        progress.Error(UrlConfig, $"Error - when applying copy {UrlConfig.SafeUrl()} to {url.SafeUrl()} - the copy needs to have a different name than the parent (use @name = xxx)");
                    }
                    else
                    {
                        progress.ApplyingCopy(url, UrlConfig);
                        file.AddConfig(clone);
                    }
                }
                catch (Exception ex)
                {
                    progress.Exception(UrlConfig, $"Exception while applying copy {UrlConfig.SafeUrl()} to {url.SafeUrl()}", ex);
                }
            }
        }
Example #2
0
        public void Apply(LinkedList <IProtoUrlConfig> databaseConfigs, IPatchProgress progress, IBasicLogger logger)
        {
            if (databaseConfigs == null)
            {
                throw new ArgumentNullException(nameof(databaseConfigs));
            }
            if (progress == null)
            {
                throw new ArgumentNullException(nameof(progress));
            }
            if (logger == null)
            {
                throw new ArgumentNullException(nameof(logger));
            }

            PatchContext context = new PatchContext(UrlConfig, databaseConfigs, logger, progress);

            for (LinkedListNode <IProtoUrlConfig> listNode = databaseConfigs.First; listNode != null; listNode = listNode.Next)
            {
                IProtoUrlConfig protoConfig = listNode.Value;
                try
                {
                    if (!NodeMatcher.IsMatch(protoConfig.Node))
                    {
                        continue;
                    }

                    ConfigNode clone = MMPatchLoader.ModifyNode(new NodeStack(protoConfig.Node), UrlConfig.config, context);
                    if (protoConfig.Node.GetValue("name") is string name && name == clone.GetValue("name"))
                    {
                        progress.Error(UrlConfig, $"Error - when applying copy {UrlConfig.SafeUrl()} to {protoConfig.FullUrl} - the copy needs to have a different name than the parent (use @name = xxx)");
                    }
                    else
                    {
                        progress.ApplyingCopy(protoConfig, UrlConfig);
                        listNode = databaseConfigs.AddAfter(listNode, new ProtoUrlConfig(protoConfig.UrlFile, clone));
                    }
                }
Example #3
0
        private void ApplyPatches(string stage, IEnumerable <UrlDir.UrlConfig> patches)
        {
            logger.Info(stage + " pass");
            Activity = "ModuleManager " + stage;

            foreach (UrlDir.UrlConfig mod in patches)
            {
                try
                {
                    string  name = mod.type.RemoveWS();
                    Command cmd  = CommandParser.Parse(name, out string tmp);

                    if (cmd == Command.Insert)
                    {
                        logger.Warning("Warning - Encountered insert node that should not exist at this stage: " + mod.SafeUrl());
                        continue;
                    }
                    else if (cmd != Command.Edit && cmd != Command.Copy && cmd != Command.Delete)
                    {
                        logger.Warning("Invalid command encountered on a patch: " + mod.SafeUrl());
                        continue;
                    }

                    string       upperName = name.ToUpper();
                    PatchContext context   = new PatchContext(mod, databaseRoot, logger, progress);
                    char[]       sep       = { '[', ']' };
                    string       condition = "";

                    if (upperName.Contains(":HAS["))
                    {
                        int start = upperName.IndexOf(":HAS[");
                        condition = name.Substring(start + 5, name.LastIndexOf(']') - start - 5);
                        name      = name.Substring(0, start);
                    }

                    string[] splits   = name.Split(sep, 3);
                    string[] patterns = splits.Length > 1 ? splits[1].Split(',', '|') : null;
                    string   type     = splits[0].Substring(1);

                    bool loop = mod.config.HasNode("MM_PATCH_LOOP");

                    foreach (UrlDir.UrlFile file in allConfigFiles)
                    {
                        if (cmd == Command.Edit)
                        {
                            foreach (UrlDir.UrlConfig url in file.configs)
                            {
                                if (!IsMatch(url, type, patterns, condition))
                                {
                                    continue;
                                }
                                if (loop)
                                {
                                    logger.Info("Looping on " + mod.SafeUrl() + " to " + url.SafeUrl());
                                }

                                do
                                {
                                    progress.ApplyingUpdate(url, mod);
                                    url.config = MMPatchLoader.ModifyNode(new NodeStack(url.config), mod.config, context);
                                } while (loop && IsMatch(url, type, patterns, condition));

                                if (loop)
                                {
                                    url.config.RemoveNodes("MM_PATCH_LOOP");
                                }
                            }
                        }
                        else if (cmd == Command.Copy)
                        {
                            // Avoid checking the new configs we are creating
                            int count = file.configs.Count;
                            for (int i = 0; i < count; i++)
                            {
                                UrlDir.UrlConfig url = file.configs[i];
                                if (!IsMatch(url, type, patterns, condition))
                                {
                                    continue;
                                }

                                ConfigNode clone = MMPatchLoader.ModifyNode(new NodeStack(url.config), mod.config, context);
                                if (url.config.HasValue("name") && url.config.GetValue("name") == clone.GetValue("name"))
                                {
                                    progress.Error(mod, $"Error - when applying copy {mod.SafeUrl()} to {url.SafeUrl()} - the copy needs to have a different name than the parent (use @name = xxx)");
                                }
                                else
                                {
                                    progress.ApplyingCopy(url, mod);
                                    file.AddConfig(clone);
                                }
                            }
                        }
                        else if (cmd == Command.Delete)
                        {
                            int i = 0;
                            while (i < file.configs.Count)
                            {
                                UrlDir.UrlConfig url = file.configs[i];

                                if (IsMatch(url, type, patterns, condition))
                                {
                                    progress.ApplyingDelete(url, mod);
                                    file.configs.RemoveAt(i);
                                }
                                else
                                {
                                    i++;
                                }
                            }
                        }
                        else
                        {
                            throw new NotImplementedException("This code should not be reachable");
                        }
                    }
                    progress.PatchApplied();
                }
                catch (Exception e)
                {
                    progress.Exception(mod, "Exception while processing node : " + mod.SafeUrl(), e);

                    try
                    {
                        logger.Error("Processed node was\n" + mod.PrettyPrint());
                    }
                    catch (Exception ex2)
                    {
                        logger.Exception("Exception while attempting to print a node", ex2);
                    }
                }
            }
        }
Example #4
0
        public void TestApply()
        {
            UrlDir.UrlFile file = UrlBuilder.CreateFile("abc/def.cfg");

            UrlDir.UrlConfig urlConfig1 = UrlBuilder.CreateConfig(new TestConfigNode("NODE")
            {
                { "foo", "bar" },
            }, file);

            UrlDir.UrlConfig urlConfig2 = UrlBuilder.CreateConfig(new TestConfigNode("NODE")
            {
                { "foo", "bar" },
            }, file);

            UrlDir.UrlConfig urlConfig3 = UrlBuilder.CreateConfig(new ConfigNode("NODE"), file);
            UrlDir.UrlConfig urlConfig4 = UrlBuilder.CreateConfig(new ConfigNode("NODE"), file);

            INodeMatcher nodeMatcher = Substitute.For <INodeMatcher>();

            nodeMatcher.IsMatch(urlConfig1.config).Returns(false);
            nodeMatcher.IsMatch(urlConfig2.config).Returns(true);
            nodeMatcher.IsMatch(urlConfig3.config).Returns(false);
            nodeMatcher.IsMatch(urlConfig4.config).Returns(true);

            CopyPatch patch = new CopyPatch(UrlBuilder.CreateConfig("ghi/jkl", new TestConfigNode("@NODE")
            {
                { "@foo", "baz" },
                { "pqr", "stw" },
            }), nodeMatcher, Substitute.For <IPassSpecifier>());

            IPatchProgress progress = Substitute.For <IPatchProgress>();
            IBasicLogger   logger   = Substitute.For <IBasicLogger>();

            patch.Apply(file, progress, logger);

            Assert.Equal(6, file.configs.Count);

            Assert.Same(urlConfig1, file.configs[0]);
            AssertNodesEqual(new TestConfigNode("NODE")
            {
                { "foo", "bar" },
            }, file.configs[0].config);

            Assert.Same(urlConfig2, file.configs[1]);
            AssertNodesEqual(new TestConfigNode("NODE")
            {
                { "foo", "bar" },
            }, file.configs[1].config);

            Assert.Same(urlConfig3, file.configs[2]);
            AssertNodesEqual(new ConfigNode("NODE"), file.configs[2].config);

            Assert.Same(urlConfig4, file.configs[3]);
            AssertNodesEqual(new ConfigNode("NODE"), file.configs[3].config);

            AssertNodesEqual(new TestConfigNode("NODE")
            {
                { "foo", "baz" },
                { "pqr", "stw" },
            }, file.configs[4].config);

            AssertNodesEqual(new TestConfigNode("NODE")
            {
                { "pqr", "stw" },
            }, file.configs[5].config);

            Received.InOrder(delegate
            {
                progress.ApplyingCopy(urlConfig2, patch.UrlConfig);
                progress.ApplyingCopy(urlConfig4, patch.UrlConfig);
            });

            progress.DidNotReceiveWithAnyArgs().ApplyingUpdate(null, null);
            progress.DidNotReceiveWithAnyArgs().ApplyingDelete(null, null);

            progress.DidNotReceiveWithAnyArgs().Error(null, null);
            progress.DidNotReceiveWithAnyArgs().Exception(null, null);
            progress.DidNotReceiveWithAnyArgs().Exception(null, null, null);
        }
        public void TestApply()
        {
            UrlDir.UrlFile file = UrlBuilder.CreateFile("abc/def.cfg");

            ConfigNode config1 = new TestConfigNode("NODE")
            {
                { "foo", "bar" },
            };

            ConfigNode config2 = new TestConfigNode("NODE")
            {
                { "foo", "bar" },
            };

            ConfigNode config3 = new ConfigNode("NODE");
            ConfigNode config4 = new ConfigNode("NODE");

            INodeMatcher nodeMatcher = Substitute.For <INodeMatcher>();

            nodeMatcher.IsMatch(config1).Returns(false);
            nodeMatcher.IsMatch(config2).Returns(true);
            nodeMatcher.IsMatch(config3).Returns(false);
            nodeMatcher.IsMatch(config4).Returns(true);

            CopyPatch patch = new CopyPatch(UrlBuilder.CreateConfig("ghi/jkl", new TestConfigNode("@NODE")
            {
                { "@foo", "baz" },
                { "pqr", "stw" },
            }), nodeMatcher, Substitute.For <IPassSpecifier>());

            IProtoUrlConfig protoUrlConfig1 = Substitute.For <IProtoUrlConfig>();
            IProtoUrlConfig protoUrlConfig2 = Substitute.For <IProtoUrlConfig>();
            IProtoUrlConfig protoUrlConfig3 = Substitute.For <IProtoUrlConfig>();
            IProtoUrlConfig protoUrlConfig4 = Substitute.For <IProtoUrlConfig>();

            protoUrlConfig1.Node.Returns(config1);
            protoUrlConfig2.Node.Returns(config2);
            protoUrlConfig3.Node.Returns(config3);
            protoUrlConfig4.Node.Returns(config4);

            protoUrlConfig1.UrlFile.Returns(file);
            protoUrlConfig2.UrlFile.Returns(file);
            protoUrlConfig3.UrlFile.Returns(file);
            protoUrlConfig4.UrlFile.Returns(file);

            LinkedList <IProtoUrlConfig> configs = new LinkedList <IProtoUrlConfig>();

            configs.AddLast(protoUrlConfig1);
            configs.AddLast(protoUrlConfig2);
            configs.AddLast(protoUrlConfig3);
            configs.AddLast(protoUrlConfig4);

            IPatchProgress progress = Substitute.For <IPatchProgress>();
            IBasicLogger   logger   = Substitute.For <IBasicLogger>();

            patch.Apply(configs, progress, logger);

            IProtoUrlConfig[] newConfigs = configs.ToArray();

            Assert.Equal(6, newConfigs.Length);

            Assert.Same(protoUrlConfig1, newConfigs[0]);
            AssertNodesEqual(new TestConfigNode("NODE")
            {
                { "foo", "bar" },
            }, newConfigs[0].Node);

            Assert.Same(protoUrlConfig2, newConfigs[1]);
            AssertNodesEqual(new TestConfigNode("NODE")
            {
                { "foo", "bar" },
            }, newConfigs[1].Node);

            AssertNodesEqual(new TestConfigNode("NODE")
            {
                { "foo", "baz" },
                { "pqr", "stw" },
            }, newConfigs[2].Node);
            Assert.Same(file, newConfigs[2].UrlFile);

            Assert.Same(protoUrlConfig3, newConfigs[3]);
            AssertNodesEqual(new ConfigNode("NODE"), newConfigs[3].Node);

            Assert.Same(protoUrlConfig4, newConfigs[4]);
            AssertNodesEqual(new ConfigNode("NODE"), newConfigs[4].Node);

            AssertNodesEqual(new TestConfigNode("NODE")
            {
                { "pqr", "stw" },
            }, newConfigs[5].Node);
            Assert.Same(file, newConfigs[5].UrlFile);

            Received.InOrder(delegate
            {
                progress.ApplyingCopy(protoUrlConfig2, patch.UrlConfig);
                progress.ApplyingCopy(protoUrlConfig4, patch.UrlConfig);
            });

            progress.DidNotReceiveWithAnyArgs().ApplyingUpdate(null, null);
            progress.DidNotReceiveWithAnyArgs().ApplyingDelete(null, null);

            progress.DidNotReceiveWithAnyArgs().Error(null, null);
            progress.DidNotReceiveWithAnyArgs().Exception(null, null);
            progress.DidNotReceiveWithAnyArgs().Exception(null, null, null);
        }