public async Task DiffCreateAndApply(byte[] src, byte[] dest, DiffMethod method) { await using var ms = new MemoryStream(); switch (method) { case DiffMethod.Default: await Utils.CreatePatch(src, dest, ms); break; case DiffMethod.BSDiff: BSDiff.Create(src, dest, ms); break; case DiffMethod.OctoDiff: OctoDiff.Create(src, dest, ms); break; default: throw new ArgumentOutOfRangeException(nameof(method), method, null); } ms.Position = 0; var patch = ms.ToArray(); await using var resultStream = new MemoryStream(); Utils.ApplyPatch(new MemoryStream(src), () => new MemoryStream(patch), resultStream); Assert.Equal(dest, resultStream.ToArray()); }
private void BuildArchivePatches(string archive_sha, IEnumerable <PatchedFromArchive> group, Dictionary <string, string> absolute_paths) { var archive = IndexedArchives.First(a => a.Hash == archive_sha); var paths = group.Select(g => g.From).ToHashSet(); var streams = new Dictionary <string, MemoryStream>(); Status($"Extracting {paths.Count} patch files from {archive.Name}"); // First we fetch the source files from the input archive using (var a = new ArchiveFile(archive.AbsolutePath)) { a.Extract(entry => { if (!paths.Contains(entry.FileName)) { return(null); } var result = new MemoryStream(); streams.Add(entry.FileName, result); return(result); }, false); } /* * using (var a = ArchiveFactory.Open(archive.AbsolutePath)) * { * foreach (var entry in a.Entries) * { * var path = entry.Key.Replace("/", "\\"); * if (!paths.Contains(path)) continue; * var result = new MemoryStream(); * streams.Add(path, result); * Info("Extracting {0}", path); * using (var stream = entry.OpenEntryStream()) * stream.CopyTo(result); * } * }*/ var extracted = streams.ToDictionary(k => k.Key, v => v.Value.ToArray()); // Now Create the patches Status("Building Patches for {0}", archive.Name); group.PMap(entry => { Info("Patching {0}", entry.To); var ss = extracted[entry.From]; using (var origin = new MemoryStream(ss)) using (var output = new MemoryStream()) { var a = origin.ReadAll(); var b = LoadDataForTo(entry.To, absolute_paths); BSDiff.Create(a, b, output); entry.Patch = output.ToArray().ToBase64(); } }); }
private void BuildArchivePatches(string archive_sha, IEnumerable <PatchedFromArchive> group, Dictionary <string, string> absolute_paths) { var archive = VFS.HashIndex[archive_sha]; using (var files = VFS.StageWith(group.Select(g => VFS.FileForArchiveHashPath(g.ArchiveHashPath)))) { var by_path = files.GroupBy(f => string.Join("|", f.Paths.Skip(1))).ToDictionary(f => f.Key, f => f.First()); // Now Create the patches group.PMap(entry => { Info("Patching {0}", entry.To); using (var origin = by_path[string.Join("|", entry.ArchiveHashPath.Skip(1))].OpenRead()) using (var output = new MemoryStream()) { var a = origin.ReadAll(); var b = LoadDataForTo(entry.To, absolute_paths); BSDiff.Create(a, b, output); entry.Patch = output.ToArray().ToBase64(); Info($"Patch size {entry.Patch.Length} for {entry.To}"); } }); } }
private Func <RawSourceFile, Directive> PatchStockESMs() { return(source => { string filename = Path.GetFileName(source.Path); string game_file = Path.Combine(GamePath, "Data", filename); if (Consts.GameESMs.Contains(filename) && source.Path.StartsWith("mods\\") && File.Exists(game_file)) { Info($"A ESM named {filename} was found in a mod that shares a name with a core game ESMs, it is assumed this is a cleaned ESM and it will be binary patched."); var result = source.EvolveTo <CleanedESM>(); result.SourceESMHash = VFS.Lookup(game_file).Hash; Status($"Generating patch of {filename}"); using (var ms = new MemoryStream()) { BSDiff.Create(File.ReadAllBytes(game_file), File.ReadAllBytes(source.AbsolutePath), ms); result.SourceData = ms.ToArray().ToBase64(); } Info($"Generated a {result.SourceData.Length} byte patch for {filename}"); return result; } return null; }); }