예제 #1
0
        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());
        }
예제 #2
0
        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();
                    }
            });
        }
예제 #3
0
        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}");
                        }
                });
            }
        }
예제 #4
0
        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;
            });
        }