Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions src/c#/GeneralUpdate.Core/Configuration/AbstractBootstrap.cs
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,9 @@ public TBootstrap Option<T>(UpdateOption<T> option, T value)
public TBootstrap SslPolicy<T>() where T : Security.ISslValidationPolicy, new()
{ _extensions[typeof(Security.ISslValidationPolicy)] = typeof(T); return (TBootstrap)this; }

public TBootstrap BinaryDiffer<T>() where T : Differential.IBinaryDiffer, new()
{ _extensions[typeof(Differential.IBinaryDiffer)] = typeof(T); return (TBootstrap)this; }

public TBootstrap DownloadPolicy<T>() where T : Download.Abstractions.IDownloadPolicy, new()
{ _extensions[typeof(Download.Abstractions.IDownloadPolicy)] = typeof(T); return (TBootstrap)this; }

Expand Down
40 changes: 40 additions & 0 deletions src/c#/GeneralUpdate.Core/Differential/IBinaryDiffer.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
using System.IO;
using System.Threading;
using System.Threading.Tasks;

namespace GeneralUpdate.Core.Differential
{
/// <summary>
/// Defines a pluggable binary differential algorithm (diff generation and patch application).
/// Implementations may use different strategies: BSDIFF, HDiffPatch-style, VCDIFF, etc.
/// </summary>
/// <remarks>
/// This interface lives in Core so that Pipeline middleware can depend on it
/// without creating a circular dependency on the GeneralUpdate.Differential assembly.
///
/// Concrete implementations (StreamingHdiffDiffer, BSDIFF, etc.) live in
/// GeneralUpdate.Differential and are injected via Bootstrap.BinaryDiffer&lt;T&gt;().
/// </remarks>
public interface IBinaryDiffer
{
/// <summary>
/// Generates a binary patch from <paramref name="oldFilePath"/> to <paramref name="newFilePath"/>,
/// writing the result to <paramref name="patchFilePath"/>.
/// </summary>
Task CleanAsync(
string oldFilePath,
string newFilePath,
string patchFilePath,
CancellationToken cancellationToken = default);

/// <summary>
/// Applies a binary patch to <paramref name="oldFilePath"/>, producing
/// <paramref name="newFilePath"/> using the patch at <paramref name="patchFilePath"/>.
/// </summary>
Task DirtyAsync(
string oldFilePath,
string newFilePath,
string patchFilePath,
CancellationToken cancellationToken = default);
}
}
45 changes: 39 additions & 6 deletions src/c#/GeneralUpdate.Core/Pipeline/PatchMiddleware.cs
Original file line number Diff line number Diff line change
@@ -1,21 +1,54 @@
using System;
using System.Threading.Tasks;
using GeneralUpdate.Core.Differential;
using GeneralUpdate.Core.Pipeline;
using GeneralUpdate.Core;

namespace GeneralUpdate.Core.Pipeline;

/// <summary>
/// Differential patch middleware.
/// Full implementation requires GeneralUpdate.Differential (circular dependency — see T2).
/// Currently a no-op placeholder; patches are applied externally.
/// Differential patch middleware. Applies binary patches (BSDIFF, HDiffPatch, etc.)
/// to bring files from an old version to a new version.
///
/// The <see cref="IBinaryDiffer"/> implementation is injected via
/// <c>Bootstrap.BinaryDiffer&lt;T&gt;()</c>. Without injection, patches are skipped.
/// </summary>
public class PatchMiddleware : IMiddleware
{
private readonly IBinaryDiffer? _differ;

/// <summary>Parameterless constructor (required by PipelineBuilder). Uses no differ.</summary>
public PatchMiddleware() { }

/// <summary>Creates a PatchMiddleware with an optional differ.</summary>
/// <param name="differ">Binary differ implementation. If null, patches are skipped.</param>
public PatchMiddleware(IBinaryDiffer? differ)
{
_differ = differ;
}

public async Task InvokeAsync(PipelineContext context)
{
GeneralTracer.Info("PatchMiddleware.InvokeAsync: differential patching is not available in this build. " +
"IBinaryDiffer injection via Bootstrap.BinaryDiffer<T>() will be re-enabled in a future PR.");
await Task.CompletedTask;
var sourcePath = context.Get<string>("SourcePath");
var targetPath = context.Get<string>("PatchPath");

if (_differ == null)
{
GeneralTracer.Info("PatchMiddleware.InvokeAsync: no IBinaryDiffer injected — patch skipped. " +
"Use Bootstrap.BinaryDiffer<T>() to enable differential patching.");
return;
}

GeneralTracer.Info($"PatchMiddleware.InvokeAsync: applying differential patch. SourcePath={sourcePath}, PatchPath={targetPath}");
try
{
await _differ.DirtyAsync(sourcePath, targetPath, targetPath);
GeneralTracer.Info("PatchMiddleware.InvokeAsync: differential patch applied successfully.");
}
catch (Exception ex)
{
GeneralTracer.Error("PatchMiddleware.InvokeAsync: failed to apply differential patch.", ex);
throw;
}
}
}
46 changes: 10 additions & 36 deletions src/c#/GeneralUpdate.Differential/Abstractions/IBinaryDiffer.cs
Original file line number Diff line number Diff line change
@@ -1,46 +1,20 @@
using System.IO;
using System.Threading;
using System.Threading.Tasks;
// IBinaryDiffer has been moved to GeneralUpdate.Core.Differential.
// This file provides a backward-compatible type alias.
// New code should reference GeneralUpdate.Core.Differential.IBinaryDiffer directly.

using CoreBinaryDiffer = GeneralUpdate.Core.Differential.IBinaryDiffer;

namespace GeneralUpdate.Differential.Abstractions
{
/// <summary>
/// Defines a pluggable binary differential algorithm (diff generation and patch application).
/// Implementations may use different strategies: BSDIFF, HDiffPatch-style, VCDIFF, etc.
/// Binary differential algorithm abstraction.
/// </summary>
/// <remarks>
/// Implementations should document their thread-safety guarantees.
/// Callers should not assume a single instance is safe for concurrent use
/// unless the implementation explicitly states so.
/// <b>Migration note:</b> This interface is an alias for
/// <see cref="CoreBinaryDiffer"/>. Use
/// <c>using GeneralUpdate.Core.Differential;</c> directly in new code.
/// </remarks>
public interface IBinaryDiffer
public interface IBinaryDiffer : CoreBinaryDiffer
{
/// <summary>
/// Generates a binary patch from <paramref name="oldFilePath"/> to <paramref name="newFilePath"/>,
/// writing the result to <paramref name="patchFilePath"/>.
/// </summary>
/// <param name="oldFilePath">Old version file path.</param>
/// <param name="newFilePath">New version file path.</param>
/// <param name="patchFilePath">Output patch file path.</param>
/// <param name="cancellationToken">Optional cancellation token.</param>
Task CleanAsync(
string oldFilePath,
string newFilePath,
string patchFilePath,
CancellationToken cancellationToken = default);

/// <summary>
/// Applies a binary patch to <paramref name="oldFilePath"/>, producing
/// <paramref name="newFilePath"/> using the patch at <paramref name="patchFilePath"/>.
/// </summary>
/// <param name="oldFilePath">Existing (old) file to patch.</param>
/// <param name="newFilePath">Output (new) file path.</param>
/// <param name="patchFilePath">Input patch file path.</param>
/// <param name="cancellationToken">Optional cancellation token.</param>
Task DirtyAsync(
string oldFilePath,
string newFilePath,
string patchFilePath,
CancellationToken cancellationToken = default);
}
}
Loading