Esempio n. 1
0
        private static void ExtractAllWithBSA(string source, string dest)
        {
            try
            {
                using (var arch = BSADispatch.OpenRead(source))
                {
                    arch.Files.PMap(f =>
                    {
                        var path = f.Path;
                        if (f.Path.StartsWith("\\"))
                        {
                            path = f.Path.Substring(1);
                        }
                        Utils.Status($"Extracting {path}");
                        var out_path = Path.Combine(dest, path);
                        var parent   = Path.GetDirectoryName(out_path);

                        if (!Directory.Exists(parent))
                        {
                            Directory.CreateDirectory(parent);
                        }

                        using (var fs = File.OpenWrite(out_path))
                        {
                            f.CopyDataTo(fs);
                        }
                    });
                }
            }
            catch (Exception ex)
            {
                Utils.Log($"While Extracting {source}");
                throw ex;
            }
        }
Esempio n. 2
0
        public static async Task CreatePatchCached(byte[] a, byte[] b, Stream output)
        {
            await using var cmd = new SQLiteCommand(_conn);
            cmd.CommandText     = @"INSERT INTO PatchCache (FromHash, ToHash, PatchSize, Patch) 
                  VALUES (@fromHash, @toHash, @patchSize, @patch)";

            var dataA = a.xxHash();
            var dataB = b.xxHash();

            cmd.Parameters.AddWithValue("@fromHash", (long)dataA);
            cmd.Parameters.AddWithValue("@toHash", (long)dataB);

            await using var patch = new MemoryStream();

            Utils.Status("Creating Patch");
            OctoDiff.Create(a, b, patch);
            patch.Position = 0;

            cmd.Parameters.AddWithValue("@patchSize", patch.Length);
            cmd.Parameters.AddWithValue("@patch", patch.ToArray());
            try
            {
                await cmd.ExecuteNonQueryAsync();
            }
            catch (SQLiteException ex)
            {
                if (!ex.Message.StartsWith("constraint failed"))
                {
                    throw;
                }
            }
            await patch.CopyToAsync(output);
        }
Esempio n. 3
0
 private void UpdateStatus()
 {
     if (_inner.Length != 0)
     {
         Utils.Status(_message, (int)(_inner.Position * 100 / _inner.Length));
     }
 }
Esempio n. 4
0
        private static async Task ExtractAllWithBSA(WorkQueue queue, AbsolutePath source, AbsolutePath dest)
        {
            try
            {
                using var arch = BSADispatch.OpenRead(source);
                await arch.Files
                .PMap(queue, f =>
                {
                    Utils.Status($"Extracting {(string)f.Path}");
                    var outPath = f.Path.RelativeTo(dest);
                    var parent  = outPath.Parent;

                    if (!parent.IsDirectory)
                    {
                        parent.CreateDirectory();
                    }

                    using var fs = outPath.Create();
                    f.CopyDataTo(fs);
                });
            }
            catch (Exception ex)
            {
                Utils.ErrorThrow(ex, $"While Extracting {source}");
            }
        }
Esempio n. 5
0
        private static void ExtractAllWithBSA(string source, string dest)
        {
            using (var arch = new BSAReader(source))
            {
                arch.Files.PMap(f =>
                {
                    var path = f.Path;
                    if (f.Path.StartsWith("\\"))
                    {
                        path = f.Path.Substring(1);
                    }
                    Utils.Status($"Extracting {path}");
                    var out_path = Path.Combine(dest, path);
                    var parent   = Path.GetDirectoryName(out_path);

                    if (!Directory.Exists(parent))
                    {
                        Directory.CreateDirectory(parent);
                    }

                    using (var fs = File.OpenWrite(out_path))
                    {
                        f.CopyDataTo(fs);
                    }
                });
            }
        }
Esempio n. 6
0
        private static async Task ExtractAllWithBSA(WorkQueue queue, string source, string dest)
        {
            try
            {
                using (var arch = BSADispatch.OpenRead(source))
                {
                    await arch.Files
                    .PMap(queue, f =>
                    {
                        var path = f.Path;
                        if (f.Path.StartsWith("\\"))
                        {
                            path = f.Path.Substring(1);
                        }
                        Utils.Status($"Extracting {path}");
                        var outPath = Path.Combine(dest, path);
                        var parent  = Path.GetDirectoryName(outPath);

                        if (!Directory.Exists(parent))
                        {
                            Directory.CreateDirectory(parent);
                        }

                        using (var fs = File.Open(outPath, System.IO.FileMode.Create))
                        {
                            f.CopyDataTo(fs);
                        }
                    });
                }
            }
            catch (Exception ex)
            {
                Utils.ErrorThrow(ex, $"While Extracting {source}");
            }
        }
Esempio n. 7
0
        private static void ExtractAllWithInno(string source, string dest)
        {
            Utils.Log($"Extracting {Path.GetFileName(source)}");

            var info = new ProcessStartInfo
            {
                FileName               = "innounp.exe",
                Arguments              = $"-x -y -b -d\"{dest}\" \"{source}\"",
                RedirectStandardError  = true,
                RedirectStandardInput  = true,
                RedirectStandardOutput = true,
                UseShellExecute        = false,
                CreateNoWindow         = true
            };

            var p = new Process
            {
                StartInfo = info
            };

            p.Start();
            ChildProcessTracker.AddProcess(p);
            try
            {
                p.PriorityClass = ProcessPriorityClass.BelowNormal;
            }
            catch (Exception)
            {
            }

            var name = Path.GetFileName(source);

            try
            {
                while (!p.HasExited)
                {
                    var line = p.StandardOutput.ReadLine();
                    if (line == null)
                    {
                        break;
                    }
                    var percent = 0;
                    if (line.Length > 4 && line[3] == '%')
                    {
                        int.TryParse(line.Substring(0, 3), out percent);
                        Utils.Status($"Extracting {name} - {line.Trim()}", percent);
                    }
                }
            }
            catch (Exception ex)
            {
            }

            p.WaitForExit();
            if (p.ExitCode != 0)
            {
                Utils.Log(p.StandardOutput.ReadToEnd());
                Utils.Log($"Extraction error extracting {source}");
            }
        }
Esempio n. 8
0
        public static async Task <long> CreatePatchCached(Stream srcStream, Hash srcHash, Stream destStream, Hash destHash,
                                                          Stream?patchOutStream = null)
        {
            var key   = PatchKey(srcHash, destHash);
            var patch = _patchCache !.Get(key);

            if (patch != null)
            {
                if (patchOutStream == null)
                {
                    return(patch.Length);
                }

                await patchOutStream.WriteAsync(patch);

                return(patch.Length);
            }

            Utils.Status("Creating Patch");
            await using var sigStream   = new MemoryStream();
            await using var patchStream = new MemoryStream();
            OctoDiff.Create(srcStream, destStream, sigStream, patchStream);
            _patchCache.Put(key, patchStream.ToArray());

            if (patchOutStream == null)
            {
                return(patchStream.Position);
            }

            patchStream.Position = 0;
            await patchStream.CopyToAsync(patchOutStream);

            return(patchStream.Position);
        }
Esempio n. 9
0
        private static void CreateSignature(Stream oldData, FileStream sigStream)
        {
            Utils.Status("Creating Patch Signature");
            var signatureBuilder = new SignatureBuilder();

            signatureBuilder.Build(oldData, new SignatureWriter(sigStream));
            sigStream.Position = 0;
        }
Esempio n. 10
0
 public static void WaitForExitAndWarn(this Process process, TimeSpan warningTimeout, string processTitle)
 {
     if (!process.WaitForExit((int)warningTimeout.TotalMilliseconds))
     {
         Utils.Status($"{processTitle} - Taking a long time to exit.", alsoLog: true);
         process.WaitForExit();
         Utils.Status($"{processTitle} - Exited after a long period.", alsoLog: true);
     }
 }
Esempio n. 11
0
        private static Stream CreateSignature(byte[] oldData)
        {
            Utils.Status("Creating Patch Signature");
            using var oldDataStream = new MemoryStream(oldData);
            var sigStream        = new MemoryStream();
            var signatureBuilder = new SignatureBuilder();

            signatureBuilder.Build(oldDataStream, new SignatureWriter(sigStream));
            sigStream.Position = 0;
            return(sigStream);
        }
Esempio n. 12
0
 public void ReportProgress(string operation, long currentPosition, long total)
 {
     if (DateTime.Now - _lastUpdate < _updateInterval)
     {
         return;
     }
     _lastUpdate = DateTime.Now;
     if (currentPosition >= total || total < 1 || currentPosition < 0)
     {
         return;
     }
     Utils.Status(operation, new Percent(total, currentPosition));
 }
Esempio n. 13
0
        public static async Task CompactFolder(this AbsolutePath folder, WorkQueue queue, Algorithm algorithm)
        {
            var driveInfo   = folder.DriveInfo().DiskSpaceInfo;
            var clusterSize = driveInfo.SectorsPerCluster * driveInfo.BytesPerSector;

            await folder
            .EnumerateFiles(true)
            .Where(f => f.Size > clusterSize)
            .PMap(queue, async path =>
            {
                Utils.Status($"Compacting {path.FileName}");
                await path.Compact(algorithm);
            });
        }
Esempio n. 14
0
        private void UpdateStatus()
        {
            if (_inner.Length == 0)
            {
                return;
            }

            if (_queue != null)
            {
                _queue.Report(_message, Percent.FactoryPutInRange(_inner.Position, _inner.Length));
            }
            else
            {
                Utils.Status(_message, Percent.FactoryPutInRange(_inner.Position, _inner.Length));
            }
        }
Esempio n. 15
0
        private void UpdateStatus()
        {
            if (_inner.Length == 0)
            {
                return;
            }

            if (_queue != null)
            {
                _queue.Report(_message, (int)(_inner.Position * 100 / _inner.Length));
            }
            else
            {
                Utils.Status(_message, (int)(_inner.Position * 100 / _inner.Length));
            }
        }
Esempio n. 16
0
        private static async Task ExtractAllWith7Zip(AbsolutePath source, AbsolutePath dest)
        {
            Utils.Log(new GenericInfo($"Extracting {(string)source.FileName}", $"The contents of {(string)source.FileName} are being extracted to {(string)source.FileName} using 7zip.exe"));


            var process = new ProcessHelper
            {
                Path      = @"Extractors\7z.exe".RelativeTo(AbsolutePath.EntryPoint),
                Arguments = new object[] { "x", "-bsp1", "-y", $"-o\"{dest}\"", source, "-mmt=off" }
            };


            var result = process.Output.Where(d => d.Type == ProcessHelper.StreamType.Output)
                         .ForEachAsync(p =>
            {
                var(_, line) = p;
                if (line == null)
                {
                    return;
                }

                if (line.Length <= 4 || line[3] != '%')
                {
                    return;
                }

                int.TryParse(line.Substring(0, 3), out var percentInt);
                Utils.Status($"Extracting {(string)source.FileName} - {line.Trim()}", Percent.FactoryPutInRange(percentInt / 100d));
            });

            var exitCode = await process.Start();


            if (exitCode != 0)
            {
                Utils.Error(new _7zipReturnError(exitCode, source, dest, ""));
            }
            else
            {
                Utils.Status($"Extracting {source.FileName} - done", Percent.One, alsoLog: true);
            }
        }
Esempio n. 17
0
        private static async Task <ExtractedFiles> ExtractAllExe(AbsolutePath source)
        {
            var isArchive = await TestWith7z(source);

            if (isArchive)
            {
                return(await ExtractAllWith7Zip(source, null));
            }

            var dest = await TempFolder.Create();

            Utils.Log($"Extracting {(string)source.FileName}");

            var process = new ProcessHelper
            {
                Path      = @"Extractors\innounp.exe".RelativeTo(AbsolutePath.EntryPoint),
                Arguments = new object[] { "-x", "-y", "-b", $"-d\"{dest.Dir}\"", source }
            };


            var result = process.Output.Where(d => d.Type == ProcessHelper.StreamType.Output)
                         .ForEachAsync(p =>
            {
                var(_, line) = p;
                if (line == null)
                {
                    return;
                }

                if (line.Length <= 4 || line[3] != '%')
                {
                    return;
                }

                int.TryParse(line.Substring(0, 3), out var percentInt);
                Utils.Status($"Extracting {source.FileName} - {line.Trim()}", Percent.FactoryPutInRange(percentInt / 100d));
            });
            await process.Start();

            return(new ExtractedFiles(dest));
        }
Esempio n. 18
0
        private void UpdateStatus()
        {
            if (DateTime.Now - _lastUpdate < TimeSpan.FromMilliseconds(500))
            {
                return;
            }

            _lastUpdate = DateTime.Now;

            if (_inner.Length == 0)
            {
                return;
            }

            if (_queue != null)
            {
                _queue.Report(_message, Percent.FactoryPutInRange(_inner.Position, _inner.Length));
            }
            else
            {
                Utils.Status(_message, Percent.FactoryPutInRange(_inner.Position, _inner.Length));
            }
        }
Esempio n. 19
0
        public static async Task CreatePatchCached(byte[] a, byte[] b, Stream output)
        {
            var dataA = a.xxHash();
            var dataB = b.xxHash();
            var key   = PatchKey(dataA, dataB);
            var found = _patchCache !.Get(key);

            if (found != null)
            {
                await output.WriteAsync(found);

                return;
            }

            await using var patch = new MemoryStream();

            Utils.Status("Creating Patch");
            OctoDiff.Create(a, b, patch);

            _patchCache.Put(key, patch.ToArray());
            patch.Position = 0;

            await patch.CopyToAsync(output);
        }
Esempio n. 20
0
        private static async Task <Dictionary <RelativePath, T> > GatheringExtractWith7Zip <T>(WorkQueue queue, IStreamFactory sf, Definitions.FileType sig, Predicate <RelativePath> shouldExtract, Func <RelativePath, IExtractedFile, ValueTask <T> > mapfn,
                                                                                               AbsolutePath tempPath, HashSet <RelativePath> onlyFiles)
        {
            TempFile tmpFile = null;
            var      dest    = tempPath.Combine(Guid.NewGuid().ToString());

            dest.CreateDirectory();

            TempFile     spoolFile = null;
            AbsolutePath source;

            try
            {
                if (sf.Name is AbsolutePath abs)
                {
                    source = abs;
                }
                else
                {
                    spoolFile = new TempFile(tempPath.Combine(Guid.NewGuid().ToString())
                                             .WithExtension(source.Extension));
                    await using var s = await sf.GetStream();

                    await spoolFile.Path.WriteAllAsync(s);

                    source = spoolFile.Path;
                }

                Utils.Log(new GenericInfo($"Extracting {(string)source.FileName}",
                                          $"The contents of {(string)source.FileName} are being extracted to {(string)source.FileName} using 7zip.exe"));

                var process = new ProcessHelper {
                    Path = @"Extractors\7z.exe".RelativeTo(AbsolutePath.EntryPoint),
                };

                if (onlyFiles != null)
                {
                    //It's stupid that we have to do this, but 7zip's file pattern matching isn't very fuzzy
                    IEnumerable <string> AllVariants(string input)
                    {
                        yield return($"\"{input}\"");

                        yield return($"\"\\{input}\"");
                    }

                    tmpFile = new TempFile();
                    await tmpFile.Path.WriteAllLinesAsync(onlyFiles.SelectMany(f => AllVariants((string)f)).ToArray());

                    process.Arguments = new object[]
                    {
                        "x", "-bsp1", "-y", $"-o\"{dest}\"", source, $"@\"{tmpFile.Path}\"", "-mmt=off"
                    };
                }
                else
                {
                    process.Arguments = new object[] { "x", "-bsp1", "-y", $"-o\"{dest}\"", source, "-mmt=off" };
                }


                var result = process.Output.Where(d => d.Type == ProcessHelper.StreamType.Output)
                             .ForEachAsync(p =>
                {
                    var(_, line) = p;
                    if (line == null)
                    {
                        return;
                    }

                    if (line.Length <= 4 || line[3] != '%')
                    {
                        return;
                    }

                    int.TryParse(line.Substring(0, 3), out var percentInt);
                    Utils.Status($"Extracting {(string)source.FileName} - {line.Trim()}",
                                 Percent.FactoryPutInRange(percentInt / 100d));
                });

                var exitCode = await process.Start();


                if (exitCode != 0)
                {
                    Utils.ErrorThrow(new _7zipReturnError(exitCode, source, dest, ""));
                }
                else
                {
                    Utils.Status($"Extracting {source.FileName} - done", Percent.One, alsoLog: true);
                }

                var results = await dest.EnumerateFiles()
                              .PMap(queue, async f =>
                {
                    var path = f.RelativeTo(dest);
                    if (!shouldExtract(path))
                    {
                        return(((RelativePath, T)) default);
Esempio n. 21
0
 public void SetProgress(long inSize, long outSize)
 {
     Utils.Status("Extracting OMOD", Percent.FactoryPutInRange(inSize, _total));
 }
Esempio n. 22
0
        private static async Task <ExtractedFiles> ExtractAllWith7Zip(AbsolutePath source, IEnumerable <RelativePath> onlyFiles)
        {
            TempFile tmpFile = null;
            var      dest    = await TempFolder.Create();

            Utils.Log(new GenericInfo($"Extracting {(string)source.FileName}", $"The contents of {(string)source.FileName} are being extracted to {(string)source.FileName} using 7zip.exe"));

            var process = new ProcessHelper
            {
                Path = @"Extractors\7z.exe".RelativeTo(AbsolutePath.EntryPoint),
            };

            if (onlyFiles != null)
            {
                //It's stupid that we have to do this, but 7zip's file pattern matching isn't very fuzzy
                IEnumerable <string> AllVariants(string input)
                {
                    yield return($"\"{input}\"");

                    yield return($"\"\\{input}\"");
                }

                tmpFile = new TempFile();
                await tmpFile.Path.WriteAllLinesAsync(onlyFiles.SelectMany(f => AllVariants((string)f)).ToArray());

                process.Arguments = new object[]
                {
                    "x", "-bsp1", "-y", $"-o\"{dest.Dir}\"", source, $"@\"{tmpFile.Path}\"", "-mmt=off"
                };
            }
            else
            {
                process.Arguments = new object[] { "x", "-bsp1", "-y", $"-o\"{dest.Dir}\"", source, "-mmt=off" };
            }


            var result = process.Output.Where(d => d.Type == ProcessHelper.StreamType.Output)
                         .ForEachAsync(p =>
            {
                var(_, line) = p;
                if (line == null)
                {
                    return;
                }

                if (line.Length <= 4 || line[3] != '%')
                {
                    return;
                }

                int.TryParse(line.Substring(0, 3), out var percentInt);
                Utils.Status($"Extracting {(string)source.FileName} - {line.Trim()}", Percent.FactoryPutInRange(percentInt / 100d));
            });

            var exitCode = await process.Start();


            if (exitCode != 0)
            {
                Utils.Error(new _7zipReturnError(exitCode, source, dest.Dir, ""));
            }
            else
            {
                Utils.Status($"Extracting {source.FileName} - done", Percent.One, alsoLog: true);
            }

            tmpFile?.Dispose();
            return(new ExtractedFiles(dest));
        }
Esempio n. 23
0
        private static void ExtractAllWithInno(string source, string dest)
        {
            Utils.Log($"Extracting {Path.GetFileName(source)}");

            var info = new ProcessStartInfo
            {
                FileName               = @"Extractors\innounp.exe",
                Arguments              = $"-x -y -b -d\"{dest}\" \"{source}\"",
                RedirectStandardError  = true,
                RedirectStandardInput  = true,
                RedirectStandardOutput = true,
                UseShellExecute        = false,
                CreateNoWindow         = true
            };

            var p = new Process {
                StartInfo = info
            };

            p.Start();
            ChildProcessTracker.AddProcess(p);

            try
            {
                p.PriorityClass = ProcessPriorityClass.BelowNormal;
            }
            catch (Exception e)
            {
                Utils.Error(e, "Error while setting process priority level for innounp.exe");
            }

            var name = Path.GetFileName(source);

            try
            {
                while (!p.HasExited)
                {
                    var line = p.StandardOutput.ReadLine();
                    if (line == null)
                    {
                        break;
                    }

                    if (line.Length <= 4 || line[3] != '%')
                    {
                        continue;
                    }

                    int.TryParse(line.Substring(0, 3), out var percent);
                    Utils.Status($"Extracting {name} - {line.Trim()}", percent);
                }
            }
            catch (Exception e)
            {
                Utils.Error(e, "Error while reading StandardOutput for innounp.exe");
            }

            p.WaitForExitAndWarn(TimeSpan.FromSeconds(30), $"Extracting {name}");
            if (p.ExitCode == 0)
            {
                return;
            }

            Utils.Log(p.StandardOutput.ReadToEnd());
            Utils.Log($"Extraction error extracting {source}");
        }
Esempio n. 24
0
        /// <summary>
        ///     Returns true if the given extension type can be extracted
        /// </summary>
        /// <param name="v"></param>
        /// <returns></returns>
        public static bool CanExtract(string v)
        {
            var ext = Path.GetExtension(v.ToLower());

            if (ext != ".exe" && !Consts.TestArchivesBeforeExtraction.Contains(ext))
            {
                return(Consts.SupportedArchives.Contains(ext) || Consts.SupportedBSAs.Contains(ext));
            }

            if (ext == ".exe")
            {
                var info = new ProcessStartInfo
                {
                    FileName               = @"Extractors\innounp.exe",
                    Arguments              = $"-t \"{v}\" ",
                    RedirectStandardError  = true,
                    RedirectStandardInput  = true,
                    RedirectStandardOutput = true,
                    UseShellExecute        = false,
                    CreateNoWindow         = true
                };

                var p = new Process {
                    StartInfo = info
                };

                p.Start();
                ChildProcessTracker.AddProcess(p);

                var name = Path.GetFileName(v);
                while (!p.HasExited)
                {
                    var line = p.StandardOutput.ReadLine();
                    if (line == null)
                    {
                        break;
                    }

                    if (line[0] != '#')
                    {
                        continue;
                    }

                    Utils.Status($"Testing {name} - {line.Trim()}");
                }

                p.WaitForExitAndWarn(TimeSpan.FromSeconds(30), $"Testing {name}");
                return(p.ExitCode == 0);
            }


            var testInfo = new ProcessStartInfo
            {
                FileName               = @"Extractors\7z.exe",
                Arguments              = $"t \"{v}\"",
                RedirectStandardError  = true,
                RedirectStandardInput  = true,
                RedirectStandardOutput = true,
                UseShellExecute        = false,
                CreateNoWindow         = true
            };

            var testP = new Process {
                StartInfo = testInfo
            };

            testP.Start();
            ChildProcessTracker.AddProcess(testP);
            try
            {
                testP.PriorityClass = ProcessPriorityClass.BelowNormal;
            }
            catch (Exception)
            {
            }

            try
            {
                while (!testP.HasExited)
                {
                    var line = testP.StandardOutput.ReadLine();
                    if (line == null)
                    {
                        break;
                    }
                }
            } catch (Exception) {}

            testP.WaitForExitAndWarn(TimeSpan.FromSeconds(30), $"Can Extract Check {v}");
            return(testP.ExitCode == 0);
        }
Esempio n. 25
0
        private static void ExtractAllWith7Zip(string source, string dest)
        {
            Utils.Log(new GenericInfo($"Extracting {Path.GetFileName(source)}", $"The contents of {source} are being extracted to {dest} using 7zip.exe"));

            var info = new ProcessStartInfo
            {
                FileName               = @"Extractors\7z.exe",
                Arguments              = $"x -bsp1 -y -o\"{dest}\" \"{source}\" -mmt=off",
                RedirectStandardError  = true,
                RedirectStandardInput  = true,
                RedirectStandardOutput = true,
                UseShellExecute        = false,
                CreateNoWindow         = true
            };

            var p = new Process {
                StartInfo = info
            };

            p.Start();
            ChildProcessTracker.AddProcess(p);
            try
            {
                p.PriorityClass = ProcessPriorityClass.BelowNormal;
            }
            catch (Exception)
            {
            }

            var name = Path.GetFileName(source);

            try
            {
                while (!p.HasExited)
                {
                    var line = p.StandardOutput.ReadLine();
                    if (line == null)
                    {
                        break;
                    }

                    if (line.Length <= 4 || line[3] != '%')
                    {
                        continue;
                    }

                    int.TryParse(line.Substring(0, 3), out var percent);
                    Utils.Status($"Extracting {name} - {line.Trim()}", percent);
                }
            }
            catch (Exception)
            {
            }

            p.WaitForExitAndWarn(TimeSpan.FromSeconds(30), $"Extracting {name}");

            if (p.ExitCode == 0)
            {
                Utils.Status($"Extracting {name} - 100%", 100, alsoLog: true);
                return;
            }
            Utils.Error(new _7zipReturnError(p.ExitCode, source, dest, p.StandardOutput.ReadToEnd()));
        }
Esempio n. 26
0
        public static async Task <long> CreatePatchCached(Stream srcStream, Hash srcHash, Stream destStream, Hash destHash,
                                                          Stream?patchOutStream = null)
        {
            if (patchOutStream == null)
            {
                await using var rcmd = new SQLiteCommand(_conn);
                rcmd.CommandText     = "SELECT PatchSize FROM PatchCache WHERE FromHash = @fromHash AND ToHash = @toHash";
                rcmd.Parameters.AddWithValue("@fromHash", (long)srcHash);
                rcmd.Parameters.AddWithValue("@toHash", (long)destHash);

                await using var rdr = await rcmd.ExecuteReaderAsync();

                while (await rdr.ReadAsync())
                {
                    return(rdr.GetInt64(0));
                }
            }
            else
            {
                if (TryGetPatch(srcHash, destHash, out var entry))
                {
                    await patchOutStream !.WriteAsync(await entry.GetData());
                    return(entry.PatchSize);
                }
            }

            await using var cmd = new SQLiteCommand(_conn);
            cmd.CommandText     = @"INSERT INTO PatchCache (FromHash, ToHash, PatchSize, Patch) 
                  VALUES (@fromHash, @toHash, @patchSize, @patch)";

            cmd.Parameters.AddWithValue("@fromHash", (long)srcHash);
            cmd.Parameters.AddWithValue("@toHash", (long)destHash);

            Utils.Status("Creating Patch");
            await using var sigStream   = new MemoryStream();
            await using var patchStream = new MemoryStream();
            OctoDiff.Create(srcStream, destStream, sigStream, patchStream);

            cmd.Parameters.AddWithValue("@patchSize", patchStream.Length);
            cmd.Parameters.AddWithValue("@patch", patchStream.ToArray());
            try
            {
                await cmd.ExecuteNonQueryAsync();
            }
            catch (SQLiteException ex)
            {
                if (!ex.Message.StartsWith("constraint failed"))
                {
                    throw;
                }
            }

            if (patchOutStream == null)
            {
                return(patchStream.Position);
            }

            patchStream.Position = 0;
            await patchStream.CopyToAsync(patchOutStream);

            return(patchStream.Position);
        }
Esempio n. 27
0
 public ProgressReporter()
 {
     _updateInterval = TimeSpan.FromMilliseconds(100);
     _report         = (s, percent) => Utils.Status(s, percent);
 }