/// <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); }
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"); }
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); }
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 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); }
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(); }); }
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); }
public void Patch_WithAnEmptyTargetFile_Throws() { var patcher = new PatchApplier(); patcher.Patch(new PatchDefinition(), "", TestContext.DeploymentDirectory); }
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); }
//////////////////////////////////////////////////////////////////////////////////////////////////// /// <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"); }
// 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); } }
//////////////////////////////////////////////////////////////////////////////////////////////////// /// <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; } } }