Skip to content

refactor: reverse Core↔Differential dependency, make all components independent - #446

Merged
JusterZhu merged 2 commits into
masterfrom
refactor/component-independence
May 26, 2026
Merged

refactor: reverse Core↔Differential dependency, make all components independent#446
JusterZhu merged 2 commits into
masterfrom
refactor/component-independence

Conversation

@JusterZhu

Copy link
Copy Markdown
Collaborator

Summary

  • GeneralUpdate.Differential: Removed Core dependency. Now only contains binary diff algorithms (IBinaryDiffer, StreamingHdiffDiffer, BinaryHandler, compression providers). Zero project references.
  • GeneralUpdate.Core: Added Differential reference. Absorbed all orchestration types from Differential (DefaultCleanStrategy, DefaultDirtyStrategy, DiffPipeline, DifferentialCore, matchers, etc.).
  • GeneralUpdate.Bowl: Removed Core dependency. Self-contains GeneralTracer, StorageHelper, IpcEncryption, Environments, ProcessInfo. Zero project references.
  • GeneralUpdate.Drivelution: Removed Core dependency. Self-contains GeneralTracer. Zero project references.
  • GeneralUpdate.Extension: Removed Core dependency. Self-contains GeneralTracer. Zero project references.
  • Removed ICleanStrategy/IDirtyStrategy/IBinaryDiffer from Core.Differential namespace. They now live in Core.Differential (strategy interfaces) and Differential.Abstractions (IBinaryDiffer).

New Dependency Graph

GeneralUpdate.Differential          ← 0 ProjectReferences (standalone)
    ↑
GeneralUpdate.Core                  ← only references Differential

GeneralUpdate.Bowl                  ← 0 ProjectReferences (standalone)
GeneralUpdate.Drivelution           ← 0 ProjectReferences (standalone)
GeneralUpdate.Extension             ← 0 ProjectReferences (standalone)

Architecture

  • Core = orchestration layer: directory traversal, file comparison, hash verification, determines which files need diffing
  • Differential = algorithm layer: only binary diff algorithms, swappable/replaceable
  • Bowl/Drivelution/Extension: fully independent components

Verification

  • dotnet build — 0 errors across all 6 projects
  • dotnet test — 1360 tests passed, 0 failed (CoreTest: 957, DifferentialTest: 85, BowlTest: 50, DrivelutionTest: 144, ExtensionTest: 124)

🤖 Generated with Claude Code

…s independent

- GeneralUpdate.Differential: remove Core dependency, keep only binary diff
  algorithms (IBinaryDiffer, StreamingHdiffDiffer, BinaryHandler, compressors)
- GeneralUpdate.Core: add Differential reference, absorb orchestration types
  (DefaultCleanStrategy, DefaultDirtyStrategy, DiffPipeline, DifferentialCore)
- GeneralUpdate.Bowl: remove Core dependency, self-contain GeneralTracer,
  StorageHelper, IpcEncryption, Environments, ProcessInfo
- GeneralUpdate.Drivelution: remove Core dependency, self-contain GeneralTracer
- GeneralUpdate.Extension: remove Core dependency, self-contain GeneralTracer
- Remove ICleanStrategy/IDirtyStrategy/IBinaryDiffer from Core.Differential
  namespace; they live in Core.Differential (strategies) and
  Differential.Abstractions (IBinaryDiffer) respectively
- Update all test projects for new namespaces

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR restructures the C# projects to invert the CoreDifferential dependency (Core becomes the orchestration layer that depends on Differential’s algorithms) and to make Bowl, Drivelution, and Extension standalone components with no project references.

Changes:

  • Moved directory-level differential orchestration (pipeline, strategies, matchers, progress model, DifferentialCore) from GeneralUpdate.Differential into GeneralUpdate.Core.
  • Removed GeneralUpdate.Core project references from GeneralUpdate.Bowl, GeneralUpdate.Drivelution, and GeneralUpdate.Extension by copying in tracer/IPC/filesystem helpers.
  • Updated Differential tests and integration tests to use the new GeneralUpdate.Core.* namespaces and references.

Reviewed changes

Copilot reviewed 88 out of 88 changed files in this pull request and generated 20 comments.

Show a summary per file
File Description
tests/DifferentialTest/Pipeline/DiffPipelineTests.cs Update test imports to Core pipeline/models.
tests/DifferentialTest/Matchers/MatcherTests.cs Update test imports to Core + adjust comments/regions.
tests/DifferentialTest/DifferentialUpgradeIntegrationTests.cs Update integration test imports to Core pipeline/models.
tests/DifferentialTest/DifferentialTest.csproj Add Core project reference for moved orchestration APIs.
src/c#/GeneralUpdate.Extension/Tracer/WindowsOutputDebugListener.cs Add Extension-local debug-view trace listener.
src/c#/GeneralUpdate.Extension/Tracer/TextTraceListener.cs Add Extension-local file-backed trace listener.
src/c#/GeneralUpdate.Extension/Tracer/GeneralTracer.cs Add Extension-local tracer implementation.
src/c#/GeneralUpdate.Extension/GeneralUpdate.Extension.csproj Remove Core project reference to make Extension standalone.
src/c#/GeneralUpdate.Extension/Download/DownloadQueueManager.cs Swap Core tracer dependency to Extension-local tracer.
src/c#/GeneralUpdate.Extension/Core/GeneralExtensionHost.cs Swap Core tracer dependency to Extension-local tracer.
src/c#/GeneralUpdate.Drivelution/Windows/Implementation/WindowsGeneralDrivelution.cs Swap Core tracer dependency to Drivelution-local tracer.
src/c#/GeneralUpdate.Drivelution/Windows/Implementation/WindowsDriverValidator.cs Swap Core tracer dependency to Drivelution-local tracer.
src/c#/GeneralUpdate.Drivelution/Windows/Implementation/WindowsDriverBackup.cs Swap Core tracer dependency to Drivelution-local tracer.
src/c#/GeneralUpdate.Drivelution/Tracer/WindowsOutputDebugListener.cs Add Drivelution-local debug-view trace listener.
src/c#/GeneralUpdate.Drivelution/Tracer/TextTraceListener.cs Add Drivelution-local file-backed trace listener.
src/c#/GeneralUpdate.Drivelution/Tracer/GeneralTracer.cs Add Drivelution-local tracer implementation.
src/c#/GeneralUpdate.Drivelution/MacOS/Implementation/MacOsGeneralDrivelution.cs Swap Core tracer dependency to Drivelution-local tracer.
src/c#/GeneralUpdate.Drivelution/Linux/Implementation/LinuxGeneralDrivelution.cs Swap Core tracer dependency to Drivelution-local tracer.
src/c#/GeneralUpdate.Drivelution/Linux/Implementation/LinuxDriverValidator.cs Swap Core tracer dependency to Drivelution-local tracer.
src/c#/GeneralUpdate.Drivelution/Linux/Implementation/LinuxDriverBackup.cs Swap Core tracer dependency to Drivelution-local tracer.
src/c#/GeneralUpdate.Drivelution/GeneralUpdate.Drivelution.csproj Remove Core project reference to make Drivelution standalone.
src/c#/GeneralUpdate.Drivelution/GeneralDrivelution.cs Swap Core tracer dependency to Drivelution-local tracer.
src/c#/GeneralUpdate.Drivelution/Core/Pipeline/DefaultPipelineSteps.cs Swap Core tracer dependency to Drivelution-local tracer.
src/c#/GeneralUpdate.Drivelution/Core/Pipeline/BaseDriverUpdater.cs Swap Core tracer dependency to Drivelution-local tracer.
src/c#/GeneralUpdate.Drivelution/Core/Execution/CommandRunner.cs Swap Core tracer dependency to Drivelution-local tracer.
src/c#/GeneralUpdate.Drivelution/Core/DriverUpdaterFactory.cs Swap Core tracer dependency to Drivelution-local tracer.
src/c#/GeneralUpdate.Differential/Pipeline/DiffPipelineOptions.cs Remove orchestration from Differential.
src/c#/GeneralUpdate.Differential/Pipeline/DiffPipelineBuilder.cs Remove orchestration from Differential.
src/c#/GeneralUpdate.Differential/Pipeline/DiffPipeline.cs Remove orchestration from Differential.
src/c#/GeneralUpdate.Differential/Models/DiffProgress.cs Remove orchestration model from Differential.
src/c#/GeneralUpdate.Differential/Matchers/IDirtyStrategy.cs Remove orchestration API from Differential.
src/c#/GeneralUpdate.Differential/Matchers/IDirtyMatcher.cs Remove orchestration API from Differential.
src/c#/GeneralUpdate.Differential/Matchers/ICleanStrategy.cs Remove orchestration API from Differential.
src/c#/GeneralUpdate.Differential/Matchers/ICleanMatcher.cs Remove orchestration API from Differential.
src/c#/GeneralUpdate.Differential/Matchers/DefaultDirtyStrategy.cs Remove orchestration impl from Differential.
src/c#/GeneralUpdate.Differential/Matchers/DefaultDirtyMatcher.cs Remove orchestration impl from Differential.
src/c#/GeneralUpdate.Differential/Matchers/DefaultCleanStrategy.cs Remove orchestration impl from Differential.
src/c#/GeneralUpdate.Differential/Matchers/DefaultCleanMatcher.cs Remove orchestration impl from Differential.
src/c#/GeneralUpdate.Differential/GeneralUpdate.Differential.csproj Remove Core reference to keep Differential standalone.
src/c#/GeneralUpdate.Differential/DifferentialCore.cs Move orchestration entrypoint out of Differential.
src/c#/GeneralUpdate.Differential/Abstractions/IBinaryDiffer.cs Make IBinaryDiffer independent of Core and include both Clean/Dirty.
src/c#/GeneralUpdate.Core/Strategy/UpgradeUpdateStrategy.cs Update to use Differential’s IBinaryDiffer abstraction.
src/c#/GeneralUpdate.Core/Strategy/ClientUpdateStrategy.cs Update to use Differential’s IBinaryDiffer abstraction.
src/c#/GeneralUpdate.Core/Strategy/AbstractStrategy.cs Update to use Differential’s IBinaryDiffer abstraction.
src/c#/GeneralUpdate.Core/Pipeline/DiffPipelineOptions.cs Add pipeline options into Core.
src/c#/GeneralUpdate.Core/Pipeline/DiffPipelineBuilder.cs Add pipeline builder into Core.
src/c#/GeneralUpdate.Core/Pipeline/DiffPipeline.cs Add orchestrating pipeline into Core.
src/c#/GeneralUpdate.Core/Models/DiffProgress.cs Add progress model into Core.
src/c#/GeneralUpdate.Core/GeneralUpdate.Core.csproj Add project reference from Core → Differential.
src/c#/GeneralUpdate.Core/DifferentialCore.cs Add orchestration entrypoint into Core.
src/c#/GeneralUpdate.Core/Differential/IDirtyMatcher.cs Add dirty matcher interface into Core.
src/c#/GeneralUpdate.Core/Differential/ICleanMatcher.cs Add clean matcher interface into Core.
src/c#/GeneralUpdate.Core/Differential/IBinaryDiffer.cs Remove Core-owned IBinaryDiffer (moved to Differential.Abstractions).
src/c#/GeneralUpdate.Core/Differential/DefaultDirtyStrategy.cs Add default dirty strategy into Core.
src/c#/GeneralUpdate.Core/Differential/DefaultDirtyMatcher.cs Add default dirty matcher into Core.
src/c#/GeneralUpdate.Core/Differential/DefaultCleanStrategy.cs Add default clean strategy into Core.
src/c#/GeneralUpdate.Core/Differential/DefaultCleanMatcher.cs Add default clean matcher into Core.
src/c#/GeneralUpdate.Core/Configuration/AbstractBootstrap.cs Update bootstrap extension registration to Differential’s IBinaryDiffer.
src/c#/GeneralUpdate.Core/Bootstrap/GeneralUpdateBootstrap.cs Update bootstrap wiring to Differential’s IBinaryDiffer.
src/c#/GeneralUpdate.Bowl/Tracer/WindowsOutputDebugListener.cs Add Bowl-local debug-view trace listener.
src/c#/GeneralUpdate.Bowl/Tracer/TextTraceListener.cs Add Bowl-local file-backed trace listener.
src/c#/GeneralUpdate.Bowl/Tracer/GeneralTracer.cs Add Bowl-local tracer implementation.
src/c#/GeneralUpdate.Bowl/Strategys/WindowStrategy.cs Replace Core filesystem/json/env usage with Bowl-local helpers.
src/c#/GeneralUpdate.Bowl/Strategys/LinuxStrategy.cs Swap Core tracer dependency to Bowl-local tracer.
src/c#/GeneralUpdate.Bowl/Strategys/AbstractStrategy.cs Replace Core filesystem usage with Bowl-local helper.
src/c#/GeneralUpdate.Bowl/Strategies/WindowsBowlStrategy.cs Replace Core filesystem usage with Bowl-local helper.
src/c#/GeneralUpdate.Bowl/Strategies/ProcessRunner.cs Swap Core tracer dependency to Bowl-local tracer.
src/c#/GeneralUpdate.Bowl/Strategies/MacBowlStrategy.cs Swap Core tracer dependency to Bowl-local tracer.
src/c#/GeneralUpdate.Bowl/Strategies/LinuxBowlStrategy.cs Swap Core tracer dependency to Bowl-local tracer.
src/c#/GeneralUpdate.Bowl/Ipc/IpcEncryption.cs Add Bowl-local IPC crypto helper.
src/c#/GeneralUpdate.Bowl/Ipc/Environments.cs Add Bowl-local IPC environment provider using encrypted temp files.
src/c#/GeneralUpdate.Bowl/Internal/WindowsSystemInfoProvider.cs Swap Core tracer dependency to Bowl-local tracer.
src/c#/GeneralUpdate.Bowl/Internal/EnvironmentProvider.cs Swap Core config/env dependency to Bowl-local implementations.
src/c#/GeneralUpdate.Bowl/Internal/CrashReporter.cs Replace Core serialization usage with Bowl-local helper.
src/c#/GeneralUpdate.Bowl/GeneralUpdate.Bowl.csproj Remove Core project reference to make Bowl standalone.
src/c#/GeneralUpdate.Bowl/FileSystem/StorageHelper.cs Add Bowl-local filesystem + JSON utilities.
src/c#/GeneralUpdate.Bowl/Configuration/ProcessInfo.cs Add Bowl-local minimal ProcessInfo model.
src/c#/GeneralUpdate.Bowl/Bowl.cs Update Bowl implementation to use Bowl-local helpers/types.
src/c#/DifferentialTest/Pipeline/DiffPipelineTests.cs Update test imports to Core pipeline/models.
src/c#/DifferentialTest/Pipeline/DiffPipelineOptionsTests.cs Update test imports to Core pipeline options.
src/c#/DifferentialTest/Pipeline/DiffPipelineIntegrationTests.cs Update test imports to Core pipeline/models.
src/c#/DifferentialTest/Pipeline/DiffPipelineBuilderTests.cs Update test imports to Core pipeline/models.
src/c#/DifferentialTest/Models/DiffProgressTests.cs Update test imports to Core progress model.
src/c#/DifferentialTest/Matchers/DefaultDirtyStrategyTests.cs Update test imports to Core differential strategy.
src/c#/DifferentialTest/Matchers/DefaultDirtyMatcherTests.cs Update test imports to Core matcher.
src/c#/DifferentialTest/Matchers/DefaultCleanStrategyTests.cs Update test imports to Core differential strategy.
src/c#/DifferentialTest/Matchers/DefaultCleanMatcherTests.cs Update test imports to Core matcher.
src/c#/DifferentialTest/DifferentialCoreTests.cs Update tests to use Core’s DifferentialCore.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +275 to +296
private static Task CopyUnknownFiles(string appPath, string patchPath)
{
return Task.Run(() =>
{
var fileManager = new StorageManager();
var comparisonResult = fileManager.Compare(appPath, patchPath);
foreach (var file in comparisonResult.DifferentNodes)
{
var extensionName = Path.GetExtension(file.FullName);
if (BlackListDefaults.DefaultBlackFormats.Contains(extensionName)) continue;

var targetFileName = file.FullName.Replace(patchPath, "").TrimStart(Path.DirectorySeparatorChar);
var targetPath = Path.Combine(appPath, targetFileName);
var parentFolder = Directory.GetParent(targetPath);
if (parentFolder?.Exists == false)
parentFolder.Create();

File.Copy(file.FullName, targetPath, true);
}

if (Directory.Exists(patchPath))
StorageManager.DeleteDirectory(patchPath);
Comment on lines +14 to +33
private static readonly byte[] _aesKey = SHA256.Create()
.ComputeHash(Encoding.UTF8.GetBytes("GeneralUpdate.IPC.EnvironmentProvider.v1"));
private static readonly byte[] _aesIV = new byte[16] { 0x47, 0x55, 0x50, 0x44, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };

private static string IpcDir
{
get
{
var dir = Path.Combine(Path.GetTempPath(), "GeneralUpdate", "ipc");
Directory.CreateDirectory(dir);
return dir;
}
}

public static void SetEnvironmentVariable(string key, string value)
{
var filePath = Path.Combine(IpcDir, $"{key}.enc");
var plainBytes = Encoding.UTF8.GetBytes(value);
IpcEncryption.EncryptToFile(plainBytes, filePath, _aesKey, _aesIV);
}
Comment on lines +28 to +33
public static void SetEnvironmentVariable(string key, string value)
{
var filePath = Path.Combine(IpcDir, $"{key}.enc");
var plainBytes = Encoding.UTF8.GetBytes(value);
IpcEncryption.EncryptToFile(plainBytes, filePath, _aesKey, _aesIV);
}
Comment on lines +7 to +8
public class TextTraceListener : TraceListener, IDisposable
{
Comment on lines +41 to +50
private void ProcessQueue()
{
foreach (var message in _messageQueue.GetConsumingEnumerable())
{
using (var fileStream = new FileStream(_filePath, FileMode.Append, FileAccess.Write, FileShare.ReadWrite))
using (var writer = new StreamWriter(fileStream))
{
writer.Write(message);
}
}
Comment on lines +19 to +30
public override void Write(string message)
{
if (!string.IsNullOrEmpty(message))
{
OutputDebugString(message);
}
}

public override void WriteLine(string message)
{
Write($"{message}{Environment.NewLine}");
}
Comment on lines +15 to +33
static GeneralTracer()
{
Trace.Listeners.Clear();

if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
Trace.Listeners.Add(new WindowsOutputDebugListener());
}

Trace.Listeners.Add(new TextWriterTraceListener(Console.Out) { Name = "ConsoleListener" });

InitializeFileListener();

if (Debugger.IsAttached)
Trace.Listeners.Add(new DefaultTraceListener());

Trace.AutoFlush = true;
_isTracingEnabled = true;
}
Comment on lines +35 to +58
private static void InitializeFileListener()
{
//Ensure that log files are rotated on a daily basis
var today = DateTime.Now.ToString("yyyy-MM-dd");
if (today == _currentLogDate && _fileListener != null)
return;

if (_fileListener != null)
{
Trace.Listeners.Remove(_fileListener);
_fileListener.Flush();
_fileListener.Close();
_fileListener.Dispose();
}

var logDir = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Logs");
Directory.CreateDirectory(logDir);

var logFileName = Path.Combine(logDir, $"generalupdate-trace {today}.log");
_fileListener = new TextTraceListener(logFileName);

Trace.Listeners.Add(_fileListener);
_currentLogDate = today;
}
Comment on lines +22 to +39
public static byte[]? DecryptFromFile(string filePath, byte[] key, byte[] iv)
{
if (!File.Exists(filePath)) return null;

try
{
var cipher = File.ReadAllBytes(filePath);
using var aes = Aes.Create();
aes.Key = key;
aes.IV = iv;
using var decryptor = aes.CreateDecryptor();
return decryptor.TransformFinalBlock(cipher, 0, cipher.Length);
}
finally
{
try { File.Delete(filePath); } catch { /* best-effort cleanup */ }
}
}
Comment on lines +1 to +4
using System;
using System.Threading;
using System.Threading.Tasks;
using GeneralUpdate.Core.Differential;
- Remove duplicate using directives in Bowl.cs
- Fix garbled characters in MatcherTests.cs region comment
- Remove unused using directives in DiffPipelineBuilder.cs

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@JusterZhu
JusterZhu merged commit 6a1f25f into master May 26, 2026
3 checks passed
@JusterZhu
JusterZhu deleted the refactor/component-independence branch May 26, 2026 10:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

refactor: reverse Core↔Differential dependency and make all components independent

2 participants