void Write(AssemblyDefinition assemblyToPatch, NPath assemblyToPatchPath, PatchOptions patchOptions = default) { // atomic write of file with backup // TODO: skip backup if existing file already patched. want the .orig to only be the unpatched file. // write to tmp and release the lock var tmpPath = assemblyToPatchPath.ChangeExtension(".tmp"); tmpPath.DeleteIfExists(); assemblyToPatch.Write(tmpPath); // $$$ , new WriterParameters { WriteSymbols = true }); see https://github.com/jbevain/cecil/issues/421 assemblyToPatch.Dispose(); // TODO: peverify obviously won't work with memory written streams. also needs all the dependencies. // solution is to create a temp folder, write the patched dll there as well as any of its direct dependencies, and run peverify if ((patchOptions & PatchOptions.SkipPeVerify) == 0) { PeVerify.Verify(tmpPath); } // move the actual file to backup, and move the tmp to actual var backupPath = ElevatedWeaver.GetPatchBackupPathFor(assemblyToPatchPath); File.Replace(tmpPath, assemblyToPatchPath, backupPath); }
private static VCDiffResult Patch(PatchOptions opt) { using (var sold = File.OpenRead(opt.OldFile)) // old file using (var snew = File.OpenRead(opt.DeltaFile)) // delta file using (var sout = File.OpenWrite(opt.NewFile)) // out file return(Decode(sold, snew, sout)); }
public void GetFilesToPatch(ConcurrentBag <FileToPatch> filesToPatch, PatchOptions patchOptions) { string msgTmpFile = Path.GetTempFileName(); _msgService.CreateMsgDat(Path.Combine(_mod.FolderPath, Constants.MsgFolderPath), msgTmpFile); filesToPatch.Add(new FileToPatch(Constants.MsgRomPath, msgTmpFile, FilePatchOptions.VariableLength | FilePatchOptions.DeleteSourceWhenDone)); }
public void GetFilesToPatch(ConcurrentBag <FileToPatch> filesToPatch, PatchOptions patchOptions) { foreach (var mapFilePath in Directory.GetFiles(Path.Combine(_mod.FolderPath, Constants.MapFolderPath))) { string mapRomPath = Path.Combine(Constants.MapFolderPath, Path.GetFileName(mapFilePath)); filesToPatch.Add(new FileToPatch(mapRomPath, mapFilePath, FilePatchOptions.VariableLength)); } }
PatchAttribute(Type type, string typeName, string methodName, Type[] methodParams, PatchOptions options = PatchOptions.None) { this.type = type; this.typeName = typeName; this.methodName = methodName; this.methodParams = methodParams; this.options = options; }
public void RunPatch(PatchOptions options) { Logger.Info("Running data patch"); var patcher = InstantiatePatcher(options); patcher.Patch(); Logger.Info("Patch completed successfully"); }
IDataPatcher InstantiatePatcher(PatchOptions options) { var type = typeof(IDataPatcher).Assembly.GetType("Catalogue.Toolbox.Patch.DataPatchers." + options.Name); if (type == null) { throw new Exception($"The data patcher '{options.Name}' couldn't be found or does not exist."); } return((IDataPatcher)Activator.CreateInstance(type)); }
public static void DrawOptions(Listing_Standard listing) { var left = listing.GetRect(Text.LineHeight * 11); // the average height of this is ~226, which is 10.2 * Text.LineHeight var right = left.RightPart(0.48f); left = left.LeftPart(0.48f); PatchOptions.DrawPatches(left); PatchOptions.DrawUnPatches(right); DubGUI.CenterText(() => listing.Label("Utilites")); }
private void PrepareForPatch() { string romPath = "romPath"; PatchOptions patchOptions = 0; _dialogService.Setup(i => i.CommitToRom(It.IsAny <ModInfo>(), out romPath, out patchOptions)).Returns(true); string failReason = "failreason"; _patchingService.Setup(i => i.CanPatch(It.IsAny <ModInfo>(), romPath, patchOptions, out failReason)).Returns(true); _dialogService.Setup(i => i.ProgressDialog(It.IsAny <Action <IProgress <ProgressInfo> > >(), It.IsAny <bool>())) .Callback((Action <IProgress <ProgressInfo> > action, bool opt) => action(null)); }
public bool CanPatch(ModInfo modInfo, string romPath, PatchOptions patchOptions, out string reasonCannotPatch) { if (patchOptions.HasFlag(PatchOptions.IncludeSprites)) { if (!_fallbackSpriteProvider.IsDefaultsPopulated) { reasonCannotPatch = "Cannot patch sprites unless 'Populate Graphics Defaults' has been run"; return(false); } } reasonCannotPatch = ""; return(true); }
public void GetFilesToPatch(ConcurrentBag <FileToPatch> filesToPatch, PatchOptions patchOptions) { if (!patchOptions.HasFlag(PatchOptions.IncludeSprites)) { return; } if (!_fallbackSpriteProvider.IsDefaultsPopulated) { throw new Exception("Cannot patch sprites unless 'Populate Graphics Defaults' has been run"); } Parallel.ForEach(GraphicsInfoResource.All, gInfo => { foreach (var builder in _builders) { builder.GetFilesToPatch(filesToPatch, gInfo); } }); }
public void AddPatch(string patchName, PatchOptions Options = null) { if (string.IsNullOrWhiteSpace(patchName)) { throw new ApplicationException("Patch Name required"); } else { var cfgWriter = new BuildConfigurationWriter(_configFileName, _configLocalFileName); var cfg = cfgWriter.Read(); // load options //DatabaseOptions dbopt = LoadDatabaseOptions(cfg); //create unique id prefix to avoid collisions string prefix = $"{DateTime.Now:yyyyMMddHHmm}-{_rand.Next(0, 9999):0000}"; // patch names are limited to 50 char total at present, but this could be a property of the plugin string finalId = $"{prefix}-{patchName.Trim()}"; finalId = finalId.Substring(0, Math.Min(50, finalId.Length)); string patchPath = _io.Path.Combine(cfg.PatchFolder, finalId); if (!_io.Directory.Exists(patchPath)) { _io.Directory.CreateDirectory(patchPath); // when adding a patch, make it dependent on all patches // that don't already have a dependency. // need to guard against circular dependencies var openPatches = cfg.GetOpenPatches(); cfg.patches.Add(new Patch(finalId, openPatches)); cfgWriter.Write(cfg); } else { // create custom exception throw new ApplicationException($"A folder named '{finalId}' already exists"); } } }
/// <summary> /// Patch kubernetes object. /// </summary> /// <typeparam name="T">the object type</typeparam> /// <param name="name"> the name</param> /// <param name="obj"> the object</param> /// <param name="patchOptions">the patch options</param> /// <param name="cancellationToken">the token </param> /// <returns>the kubernetes object</returns> public async Task <T> PatchAsync <T>(string name, object obj, PatchOptions patchOptions, CancellationToken cancellationToken = default) where T : class, IKubernetesObject <V1ObjectMeta> { if (obj == null) { throw new ArgumentNullException(nameof(obj)); } if (patchOptions == null) { throw new ArgumentNullException(nameof(patchOptions)); } if (string.IsNullOrEmpty(name)) { throw new ArgumentNullException(nameof(name)); } var resp = await _client.PatchClusterCustomObjectWithHttpMessagesAsync(body : obj, group : _apiGroup, version : _apiVersion, plural : _resourcePlural, name : name, dryRun : patchOptions.DryRun, fieldManager : patchOptions.FieldManager, force : patchOptions.Force, cancellationToken : cancellationToken).ConfigureAwait(false); return(KubernetesJson.Deserialize <T>(resp.Body.ToString())); }
public bool CommitToRom(ModInfo info, out string romPath, out PatchOptions patchOptions) { var vm = new ModCommitViewModel(this, info, _recentCommitRomSetting.Value) { IncludeSprites = _patchSpritesSetting.Value }; var dialog = new Dialogs.ModCommitDialog { Owner = Application.Current.MainWindow, DataContext = vm, }; bool?proceed = dialog.ShowDialog(); if (proceed == true) { romPath = vm.File; _recentCommitRomSetting.Value = vm.File; _patchSpritesSetting.Value = vm.IncludeSprites; _settingService.Save(); patchOptions = 0; if (vm.IncludeSprites) { patchOptions |= PatchOptions.IncludeSprites; } return(true); } else { romPath = null; patchOptions = 0; return(false); } }
public void GetFilesToPatch(ConcurrentBag <FileToPatch> filesToPatch, PatchOptions patchOptions) { List <string> dataRomPaths = new List <string>() { Constants.MoveRomPath, Constants.AbilityRomPath, Constants.WarriorSkillRomPath, Constants.GimmickRomPath, Constants.BuildingRomPath, Constants.ItemRomPath, Constants.KingdomRomPath, Constants.MoveRangeRomPath, Constants.EventSpeakerRomPath, Constants.MaxLinkRomPath, Constants.BaseBushouRomPath, Constants.BattleConfigRomPath, Constants.GimmickRangeRomPath, Constants.MoveAnimationRomPath, Constants.GimmickObjectRomPath, Constants.EpisodeRomPath }; foreach (var i in EnumUtil.GetValues <ScenarioId>()) { dataRomPaths.Add(Constants.ScenarioPokemonPathFromId((int)i)); dataRomPaths.Add(Constants.ScenarioWarriorPathFromId((int)i)); dataRomPaths.Add(Constants.ScenarioAppearPokemonPathFromId((int)i)); dataRomPaths.Add(Constants.ScenarioKingdomPathFromId((int)i)); } filesToPatch.Add(new FileToPatch(Constants.PokemonRomPath, Path.Combine(_mod.FolderPath, Constants.PokemonRomPath), FilePatchOptions.VariableLength)); foreach (string drp in dataRomPaths) { filesToPatch.Add(new FileToPatch(drp, Path.Combine(_mod.FolderPath, drp), FilePatchOptions.None)); } }
private int RunPatchOptionsCode(PatchOptions opts) { throw new NotImplementedException(); }
public static IReadOnlyCollection <PatchResult> PatchAllDependentAssemblies(NPath testAssemblyPath, PatchOptions patchOptions) { // TODO: ensure we do not have any assemblies that we want to patch already loaded // (this will require the separate in-memory patching ability) // this dll has types we're going to be injecting, so ensure it is in the same folder //var targetWeaverDll var toProcess = new List <NPath> { testAssemblyPath.FileMustExist() }; var patchResults = new Dictionary <string, PatchResult>(StringComparer.OrdinalIgnoreCase); var mockInjector = new MockInjector(testAssemblyPath.Parent.Combine("NSubstitute.Elevated")); for (var toProcessIndex = 0; toProcessIndex < toProcess.Count; ++toProcessIndex) { var assemblyToPatchPath = toProcess[toProcessIndex]; // as we accumulate dependencies recursively, we will probably get some duplicates we can early-out on if (patchResults.ContainsKey(assemblyToPatchPath)) { continue; } using (var assemblyToPatch = AssemblyDefinition.ReadAssembly(assemblyToPatchPath)) { GatherReferences(assemblyToPatchPath, assemblyToPatch); var patchResult = TryPatch(assemblyToPatchPath, assemblyToPatch); patchResults.Add(assemblyToPatchPath, patchResult); } } void GatherReferences(NPath assemblyToPatchPath, AssemblyDefinition assemblyToPatch) { foreach (var referencedAssembly in assemblyToPatch.Modules.SelectMany(m => m.AssemblyReferences)) { // only patch dll's we "own", that are in the same folder as the test assembly var referencedAssemblyPath = assemblyToPatchPath.Parent.Combine(referencedAssembly.Name + ".dll"); if (referencedAssemblyPath.FileExists()) { toProcess.Add(referencedAssemblyPath); } else if (!patchResults.ContainsKey(referencedAssembly.Name)) { patchResults.Add(referencedAssembly.Name, new PatchResult(referencedAssembly.Name, null, PatchState.IgnoredForeignAssembly)); } } } PatchResult TryPatch(NPath assemblyToPatchPath, AssemblyDefinition assemblyToPatch) { var alreadyPatched = mockInjector.IsPatched(assemblyToPatch); var cannotPatch = assemblyToPatch.Name.HasPublicKey; if (assemblyToPatchPath == testAssemblyPath && (patchOptions & PatchOptions.PatchTestAssembly) == 0) { if (alreadyPatched) { throw new Exception("Unexpected already-patched test assembly, yet we want PatchTestAssembly.No"); } if (cannotPatch) { throw new Exception("Cannot patch an assembly with a strong name"); } return(new PatchResult(assemblyToPatchPath, null, PatchState.IgnoredTestAssembly)); } if (alreadyPatched) { return(new PatchResult(assemblyToPatchPath, null, PatchState.AlreadyPatched)); } if (cannotPatch) { return(new PatchResult(assemblyToPatchPath, null, PatchState.IgnoredForeignAssembly)); } return(Patch(assemblyToPatchPath, assemblyToPatch)); } PatchResult Patch(NPath assemblyToPatchPath, AssemblyDefinition assemblyToPatch) { mockInjector.Patch(assemblyToPatch); // atomic write of file with backup // TODO: skip backup if existing file already patched. want the .orig to only be the unpatched file. // write to tmp and release the lock var tmpPath = assemblyToPatchPath.ChangeExtension(".tmp"); tmpPath.DeleteIfExists(); assemblyToPatch.Write(tmpPath); // $$$ , new WriterParameters { WriteSymbols = true }); see https://github.com/jbevain/cecil/issues/421 assemblyToPatch.Dispose(); if ((patchOptions & PatchOptions.SkipPeVerify) == 0) { PeVerify.Verify(tmpPath); } // move the actual file to backup, and move the tmp to actual var backupPath = GetPatchBackupPathFor(assemblyToPatchPath); File.Replace(tmpPath, assemblyToPatchPath, backupPath); // TODO: move pdb file too return(new PatchResult(assemblyToPatchPath, backupPath, PatchState.Patched)); } return(patchResults.Values); }
public void Patch(ModInfo modInfo, string romPath, PatchOptions patchOptions, IProgress <ProgressInfo> progress = null) { progress?.Report(new ProgressInfo(statusText: "Preparing to patch...", isIndeterminate: true)); ConcurrentBag <FileToPatch> filesToPatch = new ConcurrentBag <FileToPatch>(); Exception exception = null; try { var services = _modServiceGetterFactory.Create(modInfo); var patchers = services.Get <IEnumerable <IPatchBuilder> >(); GetFilesToPatch(patchers, filesToPatch, patchOptions); #if PATCHER_BUG_FIXING string debugOut = FileUtil.MakeUniquePath(Path.Combine(FileUtil.DesktopDirectory, "patch_debug_dump")); Directory.CreateDirectory(debugOut); foreach (var file in filesToPatch) { string dest = Path.Combine(debugOut, file.GamePath.Replace(Path.DirectorySeparatorChar, '~')); if (file.Options.HasFlag(FilePatchOptions.DeleteSourceWhenDone)) { File.Move(file.FileSystemPath, dest); } else { File.Copy(file.FileSystemPath, dest); } } return; #endif progress?.Report(new ProgressInfo(isIndeterminate: false, maxProgress: filesToPatch.Count, statusText: "Patching...")); int count = 0; using (var nds = _ndsFactory(romPath)) { foreach (var file in filesToPatch) { if (file.Options.HasFlag(FilePatchOptions.VariableLength)) { nds.InsertVariableLengthFile(file.GamePath, file.FileSystemPath); } else { nds.InsertFixedLengthFile(file.GamePath, file.FileSystemPath); } progress?.Report(new ProgressInfo(progress: ++count)); } } } catch (Exception e) { exception = e; } finally { progress?.Report(new ProgressInfo(statusText: "Cleaning up temporary files...", isIndeterminate: true)); foreach (var file in filesToPatch) { if (file.Options.HasFlag(FilePatchOptions.DeleteSourceWhenDone)) { File.Delete(file.FileSystemPath); } } } if (exception != null) { throw exception; } progress?.Report(new ProgressInfo(statusText: "Done!", isIndeterminate: false)); }
private void GetFilesToPatch(IEnumerable <IPatchBuilder> patchBuilders, ConcurrentBag <FileToPatch> filesToPatch, PatchOptions patchOptions) { Parallel.ForEach(patchBuilders, builder => { builder.GetFilesToPatch(filesToPatch, patchOptions); }); }
public PatchAttribute(PatchOptions options) : this(null, null, null, null, options) { }