2020-02-24 23:18:29 +00:00
|
|
|
|
using System;
|
|
|
|
|
using System.IO;
|
|
|
|
|
using Octodiff.Core;
|
|
|
|
|
using Octodiff.Diagnostics;
|
|
|
|
|
|
|
|
|
|
namespace Wabbajack.Common
|
|
|
|
|
{
|
|
|
|
|
public class OctoDiff
|
|
|
|
|
{
|
|
|
|
|
public static void Create(byte[] oldData, byte[] newData, Stream output)
|
|
|
|
|
{
|
|
|
|
|
using var signature = CreateSignature(oldData);
|
|
|
|
|
using var oldStream = new MemoryStream(oldData);
|
|
|
|
|
using var newStream = new MemoryStream(newData);
|
2020-08-12 22:23:02 +00:00
|
|
|
|
var db = new DeltaBuilder {ProgressReporter = new ProgressReporter()};
|
|
|
|
|
db.BuildDelta(newStream, new SignatureReader(signature, new ProgressReporter()), new AggregateCopyOperationsDecorator(new BinaryDeltaWriter(output)));
|
2020-02-24 23:18:29 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
}
|
2020-02-27 13:46:34 +00:00
|
|
|
|
|
2020-05-20 03:25:41 +00:00
|
|
|
|
private static void CreateSignature(Stream oldData, Stream sigStream)
|
2020-02-27 13:46:34 +00:00
|
|
|
|
{
|
|
|
|
|
Utils.Status("Creating Patch Signature");
|
|
|
|
|
var signatureBuilder = new SignatureBuilder();
|
|
|
|
|
signatureBuilder.Build(oldData, new SignatureWriter(sigStream));
|
|
|
|
|
sigStream.Position = 0;
|
|
|
|
|
}
|
|
|
|
|
|
2020-08-12 04:25:12 +00:00
|
|
|
|
public static void Create(Stream oldData, Stream newData, Stream signature, Stream output, ProgressReporter? reporter = null)
|
2020-02-27 13:46:34 +00:00
|
|
|
|
{
|
|
|
|
|
CreateSignature(oldData, signature);
|
2020-08-12 04:25:12 +00:00
|
|
|
|
var db = new DeltaBuilder {ProgressReporter = reporter ?? new ProgressReporter()};
|
2020-08-12 22:23:02 +00:00
|
|
|
|
db.BuildDelta(newData, new SignatureReader(signature, reporter ?? new ProgressReporter()), new AggregateCopyOperationsDecorator(new BinaryDeltaWriter(output)));
|
2020-02-27 13:46:34 +00:00
|
|
|
|
}
|
2020-02-24 23:18:29 +00:00
|
|
|
|
|
2020-08-12 04:25:12 +00:00
|
|
|
|
public class ProgressReporter : IProgressReporter
|
2020-02-24 23:18:29 +00:00
|
|
|
|
{
|
2020-03-04 05:23:08 +00:00
|
|
|
|
private DateTime _lastUpdate = DateTime.UnixEpoch;
|
2020-08-12 04:25:12 +00:00
|
|
|
|
private TimeSpan _updateInterval;
|
|
|
|
|
private Action<string, Percent> _report;
|
|
|
|
|
|
|
|
|
|
public ProgressReporter()
|
|
|
|
|
{
|
|
|
|
|
_updateInterval = TimeSpan.FromMilliseconds(100);
|
|
|
|
|
_report = (s, percent) => Utils.Status(s, percent);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public ProgressReporter(TimeSpan updateInterval, Action<string, Percent> report)
|
|
|
|
|
{
|
|
|
|
|
_updateInterval = updateInterval;
|
|
|
|
|
_report = report;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2020-02-24 23:18:29 +00:00
|
|
|
|
public void ReportProgress(string operation, long currentPosition, long total)
|
|
|
|
|
{
|
2020-03-04 05:23:08 +00:00
|
|
|
|
if (DateTime.Now - _lastUpdate < _updateInterval) return;
|
|
|
|
|
_lastUpdate = DateTime.Now;
|
2020-02-25 13:27:50 +00:00
|
|
|
|
if (currentPosition >= total || total < 1 || currentPosition < 0)
|
2020-02-25 10:58:22 +00:00
|
|
|
|
return;
|
2020-08-12 04:25:12 +00:00
|
|
|
|
_report(operation, new Percent(total, currentPosition));
|
2020-02-24 23:18:29 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static void Apply(Stream input, Func<Stream> openPatchStream, Stream output)
|
|
|
|
|
{
|
|
|
|
|
using var deltaStream = openPatchStream();
|
|
|
|
|
var deltaApplier = new DeltaApplier();
|
2020-08-12 22:23:02 +00:00
|
|
|
|
deltaApplier.Apply(input, new BinaryDeltaReader(deltaStream, new ProgressReporter()), output);
|
2020-02-24 23:18:29 +00:00
|
|
|
|
}
|
2020-02-27 13:46:34 +00:00
|
|
|
|
|
|
|
|
|
public static void Apply(FileStream input, FileStream patchStream, FileStream output)
|
|
|
|
|
{
|
|
|
|
|
var deltaApplier = new DeltaApplier();
|
2020-08-12 22:23:02 +00:00
|
|
|
|
deltaApplier.Apply(input, new BinaryDeltaReader(patchStream, new ProgressReporter()), output);
|
2020-02-27 13:46:34 +00:00
|
|
|
|
}
|
2020-02-24 23:18:29 +00:00
|
|
|
|
}
|
|
|
|
|
}
|