/// <summary>
 /// Provides patches from content packs into mod's content
 /// </summary>
 /// <param name="monitor"></param>
 public ContentPackManager(IMonitor monitor, bool paranoid = false, bool allowLegacyPacks = false)
 {
     this.monitor          = monitor;
     this.paranoid         = paranoid;
     this.allowLegacyPacks = allowLegacyPacks;
     this.packs            = new List <ManagedContentPack>();
     this.applier          = new PatchApplier(monitor, paranoid);
 }
Example #2
0
        public void Patch_WithAMissingTargetFile_ReturnsFalse()
        {
            var patcher = new PatchApplier();

            var result = patcher.Patch(new PatchDefinition(), "MissingFile.txt", TestContext.DeploymentDirectory);

            Assert.IsFalse(result, "Returned true when attempting to patch a missing file");
        }
Example #3
0
 public PatchApplierTest()
 {
     logger       = Substitute.For <IBasicLogger>();
     progress     = Substitute.For <IPatchProgress>();
     databaseRoot = UrlBuilder.CreateRoot();
     file         = UrlBuilder.CreateFile("abc/def.cfg", databaseRoot);
     patchList    = new PatchList(modList);
     patchApplier = new PatchApplier(patchList, databaseRoot, progress, logger);
 }
Example #4
0
        private bool TryApplyPatch(string patchFile, string targetFile)
        {
            using (var xmlReader = XmlReader.Create(patchFile))
            {
                var definition = PatchApplier.DeserializeDefinition(xmlReader);
                var patcher    = new PatchApplier();

                return(patcher.Patch(definition, targetFile, TestContext.DeploymentDirectory));
            }
        }
Example #5
0
        public void TestApplyPatches__PatchesNull()
        {
            PatchApplier          applier = new PatchApplier(Substitute.For <IPatchProgress>(), Substitute.For <IBasicLogger>());
            ArgumentNullException ex      = Assert.Throws <ArgumentNullException>(delegate
            {
                applier.ApplyPatches(null);
            });

            Assert.Equal("patches", ex.ParamName);
        }
		private bool TryApplyPatch(string patchFile, string targetFile)
		{
			using (var xmlReader = XmlReader.Create(patchFile))
			{
				var definition = PatchApplier.DeserializeDefinition(xmlReader);
				var patcher = new PatchApplier();

				return patcher.Patch(definition, targetFile, TestContext.DeploymentDirectory);
			}
		}
        public static bool applyPatch(ZipArchiveEntry zippedPatchFile, string patchFileName, string unmoddedMapPath, string outputPath)
        {
            createTmpDir();
            try {
                zippedPatchFile.ExtractToFile(Config.modpack_dir + @"\tmp\" + patchFileName);
            } catch (IOException) {
                rmTmpDir();
                createTmpDir();
                zippedPatchFile.ExtractToFile(Config.modpack_dir + @"\tmp\" + patchFileName);
            }
            Patch currentPatch = LoadPatch(Config.modpack_dir + @"\tmp\" + patchFileName);

            // Copy the original map to the destination path
            IO.CopyFile(unmoddedMapPath, outputPath, true);             //if modpack has written to unmoddedmap, take from backups

            // Open the destination map
            using (var stream = new EndianStream(File.Open(outputPath, FileMode.Open, FileAccess.ReadWrite), Endian.BigEndian)) {
                EngineDatabase engineDb = XMLEngineDatabaseLoader.LoadDatabase("Formats/Engines.xml");
                ICacheFile     cacheFile;
                try {
                    cacheFile = CacheFileLoader.LoadCacheFile(stream, engineDb);
                } catch (NotSupportedException nse) {
                    form1.showMsg("Error patching '" + patchFileName + "':" + nse.Message, "Error");
                    return(false);
                }
                if (!string.IsNullOrEmpty(currentPatch.BuildString) && cacheFile.BuildString != currentPatch.BuildString)
                {
                    form1.showMsg("Unable to patch. That patch is for a map with a build version of " + currentPatch.BuildString +
                                  ", and the unmodified map file doesn't match that.", "Error");
                    return(false);
                }

                if (currentPatch.MapInternalName == null)
                {
                    // Because Ascension doesn't include this, and ApplyPatch() will complain otherwise
                    currentPatch.MapInternalName = cacheFile.InternalName;
                }

                // Apply the patch!
                try {
                    PatchApplier.ApplyPatch(currentPatch, cacheFile, stream);
                } catch (ArgumentException ae) {
                    form1.showMsg("There was an issue applying the patch file '" + patchFileName + "': " + ae.Message, "Info");
                    return(false);
                }
            }

            rmTmpDir();
            return(true);
        }
Example #8
0
        public void TestApplyPatches()
        {
            IBasicLogger   logger       = Substitute.For <IBasicLogger>();
            IPatchProgress progress     = Substitute.For <IPatchProgress>();
            PatchApplier   patchApplier = new PatchApplier(progress, logger);
            IPass          pass1        = Substitute.For <IPass>();
            IPass          pass2        = Substitute.For <IPass>();
            IPass          pass3        = Substitute.For <IPass>();

            pass1.Name.Returns(":PASS1");
            pass2.Name.Returns(":PASS2");
            pass3.Name.Returns(":PASS3");

            UrlDir.UrlConfig[] patchUrlConfigs = new UrlDir.UrlConfig[9];
            IPatch[]           patches         = new IPatch[9];
            for (int i = 0; i < patches.Length; i++)
            {
                patches[i] = Substitute.For <IPatch>();
            }

            patches[0].CountsAsPatch.Returns(false);
            patches[1].CountsAsPatch.Returns(false);
            patches[2].CountsAsPatch.Returns(false);
            patches[3].CountsAsPatch.Returns(true);
            patches[4].CountsAsPatch.Returns(true);
            patches[5].CountsAsPatch.Returns(true);
            patches[6].CountsAsPatch.Returns(true);
            patches[7].CountsAsPatch.Returns(true);
            patches[8].CountsAsPatch.Returns(true);

            pass1.GetEnumerator().Returns(new ArrayEnumerator <IPatch>(patches[0], patches[1], patches[2]));
            pass2.GetEnumerator().Returns(new ArrayEnumerator <IPatch>(patches[3], patches[4], patches[5]));
            pass3.GetEnumerator().Returns(new ArrayEnumerator <IPatch>(patches[6], patches[7], patches[8]));

            IPass[] patchList = new IPass[] { pass1, pass2, pass3 };

            LinkedList <IProtoUrlConfig> databaseConfigs = Assert.IsType <LinkedList <IProtoUrlConfig> >(patchApplier.ApplyPatches(new[] { pass1, pass2, pass3 }));

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

            logger.AssertNoWarning();
            logger.AssertNoError();
            logger.AssertNoException();

            Received.InOrder(delegate
            {
                progress.PassStarted(pass1);
                patches[0].Apply(databaseConfigs, progress, logger);
                patches[1].Apply(databaseConfigs, progress, logger);
                patches[2].Apply(databaseConfigs, progress, logger);
                progress.PassStarted(pass2);
                patches[3].Apply(databaseConfigs, progress, logger);
                progress.PatchApplied();
                patches[4].Apply(databaseConfigs, progress, logger);
                progress.PatchApplied();
                patches[5].Apply(databaseConfigs, progress, logger);
                progress.PatchApplied();
                progress.PassStarted(pass3);
                patches[6].Apply(databaseConfigs, progress, logger);
                progress.PatchApplied();
                patches[7].Apply(databaseConfigs, progress, logger);
                progress.PatchApplied();
                patches[8].Apply(databaseConfigs, progress, logger);
                progress.PatchApplied();
            });
        }
Example #9
0
        public void Patch_WithAnEmptyOutputDirectory_Throws()
        {
            var patcher = new PatchApplier();

            patcher.Patch(new PatchDefinition(), @"Resources\DummyFileTwo.txt", "");
        }
		public void Patch_WithANullDefinition_Throws()
		{
			var patcher = new PatchApplier();

			patcher.Patch((PatchDefinition)null, @"Resources\DummyFileTwo.txt", TestContext.DeploymentDirectory);
		}
Example #11
0
        public void Patch_WithAnEmptyTargetFile_Throws()
        {
            var patcher = new PatchApplier();

            patcher.Patch(new PatchDefinition(), "", TestContext.DeploymentDirectory);
        }
Example #12
0
        public void Patch_WithANullDefinition_Throws()
        {
            var patcher = new PatchApplier();

            patcher.Patch((PatchDefinition)null, @"Resources\DummyFileTwo.txt", TestContext.DeploymentDirectory);
        }
        /// <summary>
        /// Patch a base rom with a given set of patches (passed as file paths).
        /// </summary>
        /// <param name="baseRom"></param>
        /// <param name="outputFile"></param>
        /// <param name="patchPaths">
        ///     A list of filepaths to patchfiles.
        ///     These paths must exist in the output directory.
        ///     To achieve this, the `Patches` directory is currently copied during a post-build step.
        /// </param>
        public static void Patch(Stream baseRom, Stream outputFile, List <string> patchPaths)
        {
            var patchers = patchPaths.Select(path => PatcherFactory.CreatePatcher(path)).ToList();

            PatchApplier.Patch(patchers, baseRom, outputFile);
        }
Example #14
0
		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Patches a file. </summary>
		///
		/// <param name="actionData">	Information describing the action. </param>
		/// <param name="onLog">	 	The on log. </param>
		/// <param name="onError">   	The on error. </param>
		public static void FilePatcher(string actionData
			, Action<string> onLog
			, Action<string, bool> onError)
		{
			if((onLog == null) || (onError == null))
			{
				throw new ArgumentNullException("One or more required callbacks have not been supplied");
			}

			onLog("Begin FilePatcher");
			onLog(String.Format("Action data: {0}", actionData));

			// Check the custom action arguments have been set
			if (String.IsNullOrEmpty(actionData))
			{
				onError("FilePatcher: ERROR : CustomActionData not set", false);
				return;
			}

			// Split the patch arguments string, the count should be a multiple of 3
			var splitArguments = actionData.Split(new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries);
			if ((splitArguments.Length == 0) || ((splitArguments.Length % 3) > 0))
			{
				onError("FilePatcher: ERROR : Invalid number of arguments passed to the FilePatcher", false);
				return;
			}

			// Populate the patch list
			var filesToPatch = new List<PatchInstance>();
			for (int i = 0; i < splitArguments.Length; i += 3)
			{
				filesToPatch.Add(new PatchInstance()
				{
					FileID = splitArguments[i],
					FilePath = splitArguments[i + 1],
					OutputPath = splitArguments[i + 2]
				});
			}

			// Create the patcher
			var filePatcher = new PatchApplier();
			filePatcher.ErrorOccurred +=
				(sender, args) =>
				{
					onError(args.Message, true);
				};

			// Patch each file
			foreach (var patchInstance in filesToPatch)
			{
				// Log the properties for debugging if necessary
				onLog("LOG: FILEPATCHERID : " + patchInstance.FileID);
				onLog("LOG: FILEPATCHERSRCFILE : " + patchInstance.FilePath);
				onLog("LOG: FILEPATCHEROUTPATH : " + patchInstance.OutputPath);

				// Patch the file
				if(!filePatcher.Patch(patchInstance.FileID
					, patchInstance.FilePath
					, patchInstance.OutputPath))
				{
					break;
				}
			}
		}
        public void TestApplyPatches()
        {
            IBasicLogger   logger       = Substitute.For <IBasicLogger>();
            IPatchProgress progress     = Substitute.For <IPatchProgress>();
            PatchApplier   patchApplier = new PatchApplier(progress, logger);

            UrlDir.UrlFile file1 = UrlBuilder.CreateFile("abc/def.cfg");
            UrlDir.UrlFile file2 = UrlBuilder.CreateFile("ghi/jkl.cfg");
            IPass          pass1 = Substitute.For <IPass>();
            IPass          pass2 = Substitute.For <IPass>();
            IPass          pass3 = Substitute.For <IPass>();

            pass1.Name.Returns(":PASS1");
            pass2.Name.Returns(":PASS2");
            pass3.Name.Returns(":PASS3");

            UrlDir.UrlConfig[] patchUrlConfigs = new UrlDir.UrlConfig[9];
            IPatch[]           patches         = new IPatch[9];
            for (int i = 0; i < patches.Length; i++)
            {
                patches[i] = Substitute.For <IPatch>();
            }

            pass1.GetEnumerator().Returns(new ArrayEnumerator <IPatch>(patches[0], patches[1], patches[2]));
            pass2.GetEnumerator().Returns(new ArrayEnumerator <IPatch>(patches[3], patches[4], patches[5]));
            pass3.GetEnumerator().Returns(new ArrayEnumerator <IPatch>(patches[6], patches[7], patches[8]));

            IPass[] patchList = new IPass[] { pass1, pass2, pass3 };

            patchApplier.ApplyPatches(new[] { file1, file2 }, new[] { pass1, pass2, pass3 });

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

            logger.DidNotReceive().Log(LogType.Warning, Arg.Any <string>());
            logger.DidNotReceive().Log(LogType.Error, Arg.Any <string>());
            logger.DidNotReceiveWithAnyArgs().Exception(null, null);

            Received.InOrder(delegate
            {
                logger.Log(LogType.Log, ":PASS1 pass");
                patches[0].Apply(file1, progress, logger);
                patches[0].Apply(file2, progress, logger);
                progress.PatchApplied();
                patches[1].Apply(file1, progress, logger);
                patches[1].Apply(file2, progress, logger);
                progress.PatchApplied();
                patches[2].Apply(file1, progress, logger);
                patches[2].Apply(file2, progress, logger);
                progress.PatchApplied();
                logger.Log(LogType.Log, ":PASS2 pass");
                patches[3].Apply(file1, progress, logger);
                patches[3].Apply(file2, progress, logger);
                progress.PatchApplied();
                patches[4].Apply(file1, progress, logger);
                patches[4].Apply(file2, progress, logger);
                progress.PatchApplied();
                patches[5].Apply(file1, progress, logger);
                patches[5].Apply(file2, progress, logger);
                progress.PatchApplied();
                logger.Log(LogType.Log, ":PASS3 pass");
                patches[6].Apply(file1, progress, logger);
                patches[6].Apply(file2, progress, logger);
                progress.PatchApplied();
                patches[7].Apply(file1, progress, logger);
                patches[7].Apply(file2, progress, logger);
                progress.PatchApplied();
                patches[8].Apply(file1, progress, logger);
                patches[8].Apply(file2, progress, logger);
                progress.PatchApplied();
            });
        }
		public void Patch_WithAnEmptyTargetFile_Throws()
		{
			var patcher = new PatchApplier();

			patcher.Patch(new PatchDefinition(), "", TestContext.DeploymentDirectory);
		}
		public void Patch_WithAnEmptyOutputDirectory_Throws()
		{
			var patcher = new PatchApplier();

			patcher.Patch(new PatchDefinition(), @"Resources\DummyFileTwo.txt", "");
		}
		public void Patch_WithAMissingTargetFile_ReturnsFalse()
		{
			var patcher = new PatchApplier();

			var result = patcher.Patch(new PatchDefinition(), "MissingFile.txt", TestContext.DeploymentDirectory);

			Assert.IsFalse(result, "Returned true when attempting to patch a missing file");
		}
Example #19
0
        // Patch Applying
        private void btnApplyPatch_Click(object sender, RoutedEventArgs e)
        {
            try
            {
                // Check the user isn't completly retarded
                if (!CheckAllApplyMandatoryFields() || currentPatch == null)
                {
                    return;
                }

                // Check the output name
                if (cacheOutputName != "")
                {
                    if (Path.GetFileNameWithoutExtension(txtApplyPatchOutputMap.Text) != cacheOutputName)
                    {
                        if (MetroMessageBox.Show("Warning",
                                                 "This patch suggests to use the filename \"" + cacheOutputName +
                                                 ".map\" to save this map. This filename may be required in order for the map to work correctly.\r\n\r\nAre you sure you want to save this map as \"" +
                                                 Path.GetFileName(txtApplyPatchOutputMap.Text) + "\"?",
                                                 MetroMessageBox.MessageBoxButtons.OkCancel) != MetroMessageBox.MessageBoxResult.OK)
                        {
                            Close();
                            return;
                        }
                    }
                }

                // Paths
                string unmoddedMapPath = txtApplyPatchUnmodifiedMap.Text;
                string outputPath      = txtApplyPatchOutputMap.Text;

                // Copy the original map to the destination path
                File.Copy(unmoddedMapPath, outputPath, true);

                // Open the destination map
                using (var stream = new EndianStream(File.Open(outputPath, FileMode.Open, FileAccess.ReadWrite), Endian.BigEndian))
                {
                    EngineDatabase engineDb  = XMLEngineDatabaseLoader.LoadDatabase("Formats/Engines.xml");
                    ICacheFile     cacheFile = CacheFileLoader.LoadCacheFile(stream, outputPath, engineDb);
                    if (currentPatch.MapInternalName != null && cacheFile.InternalName != currentPatch.MapInternalName)
                    {
                        MetroMessageBox.Show("Unable to apply patch",
                                             "Hold on there! That patch is for " + currentPatch.MapInternalName +
                                             ".map, and the unmodified map file you selected doesn't seem to match that. Find the correct file and try again.");
                        return;
                    }
                    if (!string.IsNullOrEmpty(currentPatch.BuildString) && cacheFile.BuildString != currentPatch.BuildString)
                    {
                        MetroMessageBox.Show("Unable to apply patch",
                                             "Hold on there! That patch is for a map with a build version of" + currentPatch.BuildString +
                                             ", and the unmodified map file you selected doesn't seem to match that. Find the correct file and try again.");
                        return;
                    }

                    // Apply the patch!
                    if (currentPatch.MapInternalName == null)
                    {
                        currentPatch.MapInternalName = cacheFile.InternalName;
                    }
                    // Because Ascension doesn't include this, and ApplyPatch() will complain otherwise

                    PatchApplier.ApplyPatch(currentPatch, cacheFile, stream);

                    // Check for blf snaps
                    if (cbApplyPatchBlfExtraction.IsChecked != null &&
                        (PatchApplicationPatchExtra.Visibility == Visibility.Visible && (bool)cbApplyPatchBlfExtraction.IsChecked))
                    {
                        string extractDir   = Path.GetDirectoryName(outputPath);
                        string blfDirectory = Path.Combine(extractDir, "images");
                        string infDirectory = Path.Combine(extractDir, "info");
                        if (!Directory.Exists(blfDirectory))
                        {
                            Directory.CreateDirectory(blfDirectory);
                        }
                        if (!Directory.Exists(infDirectory))
                        {
                            Directory.CreateDirectory(infDirectory);
                        }

                        string infPath = Path.Combine(infDirectory, Path.GetFileName(currentPatch.CustomBlfContent.MapInfoFileName));
                        File.WriteAllBytes(infPath, currentPatch.CustomBlfContent.MapInfo);

                        foreach (BlfContainerEntry blfContainerEntry in currentPatch.CustomBlfContent.BlfContainerEntries)
                        {
                            string blfPath = Path.Combine(blfDirectory, Path.GetFileName(blfContainerEntry.FileName));
                            File.WriteAllBytes(blfPath, blfContainerEntry.BlfContainer);
                        }
                    }
                }

                MetroMessageBox.Show("Patch Applied!", "Your patch has been applied successfully. Have fun!");
            }
            catch (Exception ex)
            {
                MetroException.Show(ex);
            }
        }
Example #20
0
        ////////////////////////////////////////////////////////////////////////////////////////////////////
        /// <summary>	Patches a file. </summary>
        ///
        /// <param name="actionData">	Information describing the action. </param>
        /// <param name="onLog">	    The on log. </param>
        /// <param name="onError">      The on error. </param>
        public static void FilePatcher(string actionData
                                       , Action <string> onLog
                                       , Action <string, bool> onError)
        {
            if ((onLog == null) || (onError == null))
            {
                throw new ArgumentNullException("One or more required callbacks have not been supplied");
            }

            onLog("Begin FilePatcher");
            onLog(String.Format("Action data: {0}", actionData));

            // Check the custom action arguments have been set
            if (String.IsNullOrEmpty(actionData))
            {
                onError("FilePatcher: ERROR : CustomActionData not set", false);
                return;
            }

            // Split the patch arguments string, the count should be a multiple of 3
            var splitArguments = actionData.Split(new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries);

            if ((splitArguments.Length == 0) || ((splitArguments.Length % 3) > 0))
            {
                onError("FilePatcher: ERROR : Invalid number of arguments passed to the FilePatcher", false);
                return;
            }

            // Populate the patch list
            var filesToPatch = new List <PatchInstance>();

            for (int i = 0; i < splitArguments.Length; i += 3)
            {
                filesToPatch.Add(new PatchInstance()
                {
                    FileID     = splitArguments[i],
                    FilePath   = splitArguments[i + 1],
                    OutputPath = splitArguments[i + 2]
                });
            }

            // Create the patcher
            var filePatcher = new PatchApplier();

            filePatcher.ErrorOccurred +=
                (sender, args) =>
            {
                onError(args.Message, true);
            };

            // Patch each file
            foreach (var patchInstance in filesToPatch)
            {
                // Log the properties for debugging if necessary
                onLog("LOG: FILEPATCHERID : " + patchInstance.FileID);
                onLog("LOG: FILEPATCHERSRCFILE : " + patchInstance.FilePath);
                onLog("LOG: FILEPATCHEROUTPATH : " + patchInstance.OutputPath);

                // Patch the file
                if (!filePatcher.Patch(patchInstance.FileID
                                       , patchInstance.FilePath
                                       , patchInstance.OutputPath))
                {
                    break;
                }
            }
        }