From ebfa22d0dcd4ee86496f191cbfd137be049392eb Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 19 Jan 2026 05:28:01 +0000 Subject: [PATCH 1/2] Initial plan From 20b300edf271b7530f7169f0e817290913ba52cd Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 19 Jan 2026 05:34:28 +0000 Subject: [PATCH 2/2] Refactor Strategy classes to eliminate code duplication Co-authored-by: JusterZhu <11714536+JusterZhu@users.noreply.github.com> --- .../Strategys/LinuxStrategy.cs | 88 +++----------- .../Strategys/WindowsStrategy.cs | 82 +++---------- .../Internal/Strategy/AbstractStrategy.cs | 114 ++++++++++++++++- .../Strategys/LinuxStrategy.cs | 115 +++++------------- .../Strategys/WindowsStrategy.cs | 107 ++++------------ 5 files changed, 192 insertions(+), 314 deletions(-) diff --git a/src/c#/GeneralUpdate.ClientCore/Strategys/LinuxStrategy.cs b/src/c#/GeneralUpdate.ClientCore/Strategys/LinuxStrategy.cs index c005af02..8caecf2f 100644 --- a/src/c#/GeneralUpdate.ClientCore/Strategys/LinuxStrategy.cs +++ b/src/c#/GeneralUpdate.ClientCore/Strategys/LinuxStrategy.cs @@ -1,9 +1,7 @@ using System; using System.Diagnostics; using System.IO; -using System.Threading.Tasks; using GeneralUpdate.ClientCore.Pipeline; -using GeneralUpdate.Common.FileBasic; using GeneralUpdate.Common.Internal; using GeneralUpdate.Common.Internal.Bootstrap; using GeneralUpdate.Common.Internal.Event; @@ -11,8 +9,6 @@ using GeneralUpdate.Common.Internal.Strategy; using GeneralUpdate.Common.Shared; using GeneralUpdate.Common.Shared.Object; -using GeneralUpdate.Common.Shared.Object.Enum; -using GeneralUpdate.Common.Shared.Service; namespace GeneralUpdate.ClientCore.Strategys; @@ -21,76 +17,24 @@ namespace GeneralUpdate.ClientCore.Strategys; /// public class LinuxStrategy : AbstractStrategy { - private GlobalConfigInfo _configinfo = new(); - - public override void Create(GlobalConfigInfo parameter) => _configinfo = parameter; - - public override async Task ExecuteAsync() + protected override PipelineContext CreatePipelineContext(VersionInfo version, string patchPath) { - try - { - var status = ReportType.None; - var patchPath = StorageManager.GetTempDirectory(Patchs); - foreach (var version in _configinfo.UpdateVersions) - { - try - { - var context = new PipelineContext(); - //Common - context.Add("ZipFilePath", - Path.Combine(_configinfo.TempPath, $"{version.Name}{_configinfo.Format}")); - //hash middleware - context.Add("Hash", version.Hash); - //zip middleware - context.Add("Format", _configinfo.Format); - context.Add("Name", version.Name); - context.Add("Encoding", _configinfo.Encoding); - //patch middleware - context.Add("SourcePath", _configinfo.InstallPath); - context.Add("PatchPath", patchPath); - context.Add("PatchEnabled", _configinfo.PatchEnabled); - //blacklist - context.Add("BlackFiles", _configinfo.BlackFiles); - context.Add("BlackFileFormats", _configinfo.BlackFormats); - context.Add("SkipDirectorys", _configinfo.SkipDirectorys); - - var pipelineBuilder = new PipelineBuilder(context) - .UseMiddlewareIf(_configinfo.PatchEnabled) - .UseMiddleware() - .UseMiddleware(); - await pipelineBuilder.Build(); - status = ReportType.Success; - } - catch (Exception e) - { - status = ReportType.Failure; - GeneralTracer.Error("The ExecuteAsync method in the GeneralUpdate.ClientCore.LinuxStrategy class throws an exception.", e); - EventManager.Instance.Dispatch(this, new ExceptionEventArgs(e, e.Message)); - } - finally - { - await VersionService.Report(_configinfo.ReportUrl - , version.RecordId - , status - , version.AppType - , _configinfo.Scheme - , _configinfo.Token); - } - } - - if (!string.IsNullOrEmpty(_configinfo.UpdateLogUrl)) - { - OpenBrowser(_configinfo.UpdateLogUrl); - } + var context = base.CreatePipelineContext(version, patchPath); + + // Add ClientCore-specific context items (blacklists for Linux) + context.Add("BlackFiles", _configinfo.BlackFiles); + context.Add("BlackFileFormats", _configinfo.BlackFormats); + context.Add("SkipDirectorys", _configinfo.SkipDirectorys); + + return context; + } - Clear(patchPath); - Clear(_configinfo.TempPath); - } - catch (Exception e) - { - GeneralTracer.Error("The ExecuteAsync method in the GeneralUpdate.ClientCore.LinuxStrategy class throws an exception." , e); - EventManager.Instance.Dispatch(this, new ExceptionEventArgs(e, e.Message)); - } + protected override PipelineBuilder BuildPipeline(PipelineContext context) + { + return new PipelineBuilder(context) + .UseMiddlewareIf(_configinfo.PatchEnabled) + .UseMiddleware() + .UseMiddleware(); } public override void StartApp() diff --git a/src/c#/GeneralUpdate.ClientCore/Strategys/WindowsStrategy.cs b/src/c#/GeneralUpdate.ClientCore/Strategys/WindowsStrategy.cs index 814dce6b..bf25df16 100644 --- a/src/c#/GeneralUpdate.ClientCore/Strategys/WindowsStrategy.cs +++ b/src/c#/GeneralUpdate.ClientCore/Strategys/WindowsStrategy.cs @@ -1,9 +1,7 @@ using System; using System.Diagnostics; using System.IO; -using System.Threading.Tasks; using GeneralUpdate.ClientCore.Pipeline; -using GeneralUpdate.Common.FileBasic; using GeneralUpdate.Common.Internal; using GeneralUpdate.Common.Internal.Bootstrap; using GeneralUpdate.Common.Internal.Event; @@ -11,8 +9,6 @@ using GeneralUpdate.Common.Internal.Strategy; using GeneralUpdate.Common.Shared; using GeneralUpdate.Common.Shared.Object; -using GeneralUpdate.Common.Shared.Object.Enum; -using GeneralUpdate.Common.Shared.Service; namespace GeneralUpdate.ClientCore.Strategys; @@ -21,72 +17,22 @@ namespace GeneralUpdate.ClientCore.Strategys; /// public class WindowsStrategy : AbstractStrategy { - private GlobalConfigInfo _configinfo = new(); - - public override void Create(GlobalConfigInfo parameter) => _configinfo = parameter; - - public override async Task ExecuteAsync() + protected override PipelineContext CreatePipelineContext(VersionInfo version, string patchPath) { - try - { - var status = ReportType.None; - var patchPath = StorageManager.GetTempDirectory(Patchs); - foreach (var version in _configinfo.UpdateVersions) - { - try - { - var context = new PipelineContext(); - //Common - context.Add("ZipFilePath", - Path.Combine(_configinfo.TempPath, $"{version.Name}{_configinfo.Format}")); - //hash middleware - context.Add("Hash", version.Hash); - //zip middleware - context.Add("Format", _configinfo.Format); - context.Add("Name", version.Name); - context.Add("Encoding", _configinfo.Encoding); - //patch middleware - context.Add("SourcePath", _configinfo.InstallPath); - context.Add("PatchPath", patchPath); - context.Add("PatchEnabled", _configinfo.PatchEnabled); - - var pipelineBuilder = new PipelineBuilder(context) - .UseMiddlewareIf(_configinfo.PatchEnabled) - .UseMiddleware() - .UseMiddleware(); - await pipelineBuilder.Build(); - status = ReportType.Success; - } - catch (Exception e) - { - status = ReportType.Failure; - GeneralTracer.Error("The ExecuteAsync method in the GeneralUpdate.ClientCore.WindowsStrategy class throws an exception.", e); - EventManager.Instance.Dispatch(this, new ExceptionEventArgs(e, e.Message)); - } - finally - { - await VersionService.Report(_configinfo.ReportUrl - , version.RecordId - , status - , version.AppType - , _configinfo.Scheme - , _configinfo.Token); - } - } - - if (!string.IsNullOrEmpty(_configinfo.UpdateLogUrl)) - { - OpenBrowser(_configinfo.UpdateLogUrl); - } + var context = base.CreatePipelineContext(version, patchPath); + + // Add ClientCore-specific context items (blacklists are not needed for Windows in Core) + // Keeping this override to maintain extensibility + + return context; + } - Clear(patchPath); - Clear(_configinfo.TempPath); - } - catch (Exception e) - { - GeneralTracer.Error("The ExecuteAsync method in the GeneralUpdate.ClientCore.WindowsStrategy class throws an exception." , e); - EventManager.Instance.Dispatch(this, new ExceptionEventArgs(e, e.Message)); - } + protected override PipelineBuilder BuildPipeline(PipelineContext context) + { + return new PipelineBuilder(context) + .UseMiddlewareIf(_configinfo.PatchEnabled) + .UseMiddleware() + .UseMiddleware(); } public override void StartApp() diff --git a/src/c#/GeneralUpdate.Common/Internal/Strategy/AbstractStrategy.cs b/src/c#/GeneralUpdate.Common/Internal/Strategy/AbstractStrategy.cs index dacb0d97..4fb57c46 100644 --- a/src/c#/GeneralUpdate.Common/Internal/Strategy/AbstractStrategy.cs +++ b/src/c#/GeneralUpdate.Common/Internal/Strategy/AbstractStrategy.cs @@ -4,21 +4,131 @@ using System.Runtime.InteropServices; using System.Threading.Tasks; using GeneralUpdate.Common.FileBasic; +using GeneralUpdate.Common.Internal.Event; +using GeneralUpdate.Common.Internal.Pipeline; +using GeneralUpdate.Common.Shared; using GeneralUpdate.Common.Shared.Object; +using GeneralUpdate.Common.Shared.Object.Enum; +using GeneralUpdate.Common.Shared.Service; namespace GeneralUpdate.Common.Internal.Strategy { public abstract class AbstractStrategy : IStrategy { protected const string Patchs = "patchs"; + protected GlobalConfigInfo _configinfo = new(); public virtual void Execute() => throw new NotImplementedException(); public virtual void StartApp() => throw new NotImplementedException(); - public virtual Task ExecuteAsync() => throw new NotImplementedException(); + public virtual async Task ExecuteAsync() + { + try + { + var status = ReportType.None; + var patchPath = StorageManager.GetTempDirectory(Patchs); + foreach (var version in _configinfo.UpdateVersions) + { + try + { + var context = CreatePipelineContext(version, patchPath); + var pipelineBuilder = BuildPipeline(context); + await pipelineBuilder.Build(); + status = ReportType.Success; + } + catch (Exception e) + { + status = ReportType.Failure; + HandleExecuteException(e); + } + finally + { + await VersionService.Report(_configinfo.ReportUrl + , version.RecordId + , status + , version.AppType + , _configinfo.Scheme + , _configinfo.Token); + } + } + + if (!string.IsNullOrEmpty(_configinfo.UpdateLogUrl)) + { + OpenBrowser(_configinfo.UpdateLogUrl); + } + + Clear(patchPath); + Clear(_configinfo.TempPath); + OnExecuteComplete(); + } + catch (Exception e) + { + HandleExecuteException(e); + } + } + + public virtual void Create(GlobalConfigInfo parameter) => _configinfo = parameter; + + /// + /// Creates the pipeline context with common and platform-specific parameters. + /// Override this method to add platform-specific context parameters. + /// + protected virtual PipelineContext CreatePipelineContext(VersionInfo version, string patchPath) + { + var context = new PipelineContext(); + // Common parameters + context.Add("ZipFilePath", Path.Combine(_configinfo.TempPath, $"{version.Name}{_configinfo.Format}")); + // Hash middleware + context.Add("Hash", version.Hash); + // Zip middleware + context.Add("Format", _configinfo.Format); + context.Add("Name", version.Name); + context.Add("Encoding", _configinfo.Encoding); + // Patch middleware + context.Add("SourcePath", _configinfo.InstallPath); + context.Add("PatchPath", patchPath); + context.Add("PatchEnabled", _configinfo.PatchEnabled); + + return context; + } + + /// + /// Builds the pipeline with middleware components. + /// Override this method to customize the pipeline for specific platforms. + /// + protected abstract PipelineBuilder BuildPipeline(PipelineContext context); + + /// + /// Called after ExecuteAsync completes successfully. + /// Override this method to add platform-specific post-execution logic. + /// + protected virtual void OnExecuteComplete() + { + // Default implementation does nothing + } - public virtual void Create(GlobalConfigInfo parameter) => throw new NotImplementedException(); + /// + /// Handles exceptions during execution. + /// Override this method to customize error handling. + /// + protected virtual void HandleExecuteException(Exception e) + { + var className = GetType().Name; + GeneralTracer.Error($"Exception in {className}.ExecuteAsync method.", e); + EventManager.Instance.Dispatch(this, new ExceptionEventArgs(e, e.Message)); + } + + /// + /// Checks if a file exists at the specified path. + /// + protected static string CheckPath(string path, string name) + { + if (string.IsNullOrWhiteSpace(path) || string.IsNullOrWhiteSpace(name)) + return string.Empty; + var tempPath = Path.Combine(path, name); + return File.Exists(tempPath) ? tempPath : string.Empty; + } protected static void OpenBrowser(string url) { diff --git a/src/c#/GeneralUpdate.Core/Strategys/LinuxStrategy.cs b/src/c#/GeneralUpdate.Core/Strategys/LinuxStrategy.cs index 5bb961db..d52b7ca8 100644 --- a/src/c#/GeneralUpdate.Core/Strategys/LinuxStrategy.cs +++ b/src/c#/GeneralUpdate.Core/Strategys/LinuxStrategy.cs @@ -1,7 +1,6 @@ using System; using System.Diagnostics; using System.IO; -using System.Threading.Tasks; using GeneralUpdate.Common.FileBasic; using GeneralUpdate.Common.Internal; using GeneralUpdate.Common.Internal.Event; @@ -9,94 +8,43 @@ using GeneralUpdate.Common.Internal.Strategy; using GeneralUpdate.Common.Shared; using GeneralUpdate.Common.Shared.Object; -using GeneralUpdate.Common.Shared.Object.Enum; -using GeneralUpdate.Common.Shared.Service; using GeneralUpdate.Core.Pipeline; namespace GeneralUpdate.Core.Strategys; public class LinuxStrategy : AbstractStrategy { - private GlobalConfigInfo _configinfo = new(); + protected override PipelineContext CreatePipelineContext(VersionInfo version, string patchPath) + { + var context = base.CreatePipelineContext(version, patchPath); + + // Driver middleware (Linux-specific) + if (_configinfo.DriveEnabled == true) + { + context.Add("DriverOutPut", StorageManager.GetTempDirectory("DriverOutPut")); + context.Add("FieldMappings", _configinfo.FieldMappings); + } + + return context; + } - public override void Create(GlobalConfigInfo parameter) => _configinfo = parameter; + protected override PipelineBuilder BuildPipeline(PipelineContext context) + { + return new PipelineBuilder(context) + .UseMiddlewareIf(_configinfo.PatchEnabled) + .UseMiddleware() + .UseMiddleware() + .UseMiddlewareIf(_configinfo.DriveEnabled); + } public override void Execute() { - Task.Run(async () => - { - try - { - var status = ReportType.None; - var patchPath = StorageManager.GetTempDirectory(Patchs); - foreach (var version in _configinfo.UpdateVersions) - { - try - { - var context = new PipelineContext(); - //Common - context.Add("ZipFilePath", - Path.Combine(_configinfo.TempPath, $"{version.Name}{_configinfo.Format}")); - //Hash middleware - context.Add("Hash", version.Hash); - //Zip middleware - context.Add("Format", _configinfo.Format); - context.Add("Name", version.Name); - context.Add("Encoding", _configinfo.Encoding); - //Patch middleware - context.Add("SourcePath", _configinfo.InstallPath); - context.Add("PatchPath", patchPath); - context.Add("PatchEnabled", _configinfo.PatchEnabled); - //Driver middleware - if (_configinfo.DriveEnabled == true) - { - context.Add("DriverOutPut", StorageManager.GetTempDirectory("DriverOutPut")); - context.Add("FieldMappings", _configinfo.FieldMappings); - } - - var pipelineBuilder = new PipelineBuilder(context) - .UseMiddlewareIf(_configinfo.PatchEnabled) - .UseMiddleware() - .UseMiddleware() - .UseMiddlewareIf(_configinfo.DriveEnabled); - await pipelineBuilder.Build(); - status = ReportType.Success; - } - catch (Exception e) - { - status = ReportType.Failure; - GeneralTracer.Error( - "The Execute method in the GeneralUpdate.Core.WindowsStrategy class throws an exception.", - e); - EventManager.Instance.Dispatch(this, new ExceptionEventArgs(e, e.Message)); - } - finally - { - await VersionService.Report(_configinfo.ReportUrl - , version.RecordId - , status - , version.AppType - , _configinfo.Scheme - , _configinfo.Token); - } - } - - if (!string.IsNullOrEmpty(_configinfo.UpdateLogUrl)) - { - OpenBrowser(_configinfo.UpdateLogUrl); - } - - Clear(patchPath); - Clear(_configinfo.TempPath); - StartApp(); - } - catch (Exception e) - { - GeneralTracer.Error( - "The Execute method in the GeneralUpdate.Core.WindowsStrategy class throws an exception.", e); - EventManager.Instance.Dispatch(this, new ExceptionEventArgs(e, e.Message)); - } - }); + ExecuteAsync().Wait(); + } + + protected override void OnExecuteComplete() + { + StartApp(); } public override void StartApp() @@ -113,7 +61,7 @@ public override void StartApp() catch (Exception e) { GeneralTracer.Error( - "The StartApp method in the GeneralUpdate.Core.WindowsStrategy class throws an exception.", e); + "The StartApp method in the GeneralUpdate.Core.LinuxStrategy class throws an exception.", e); EventManager.Instance.Dispatch(this, new ExceptionEventArgs(e, e.Message)); } finally @@ -123,13 +71,6 @@ public override void StartApp() } } - private string CheckPath(string path, string name) - { - if (string.IsNullOrWhiteSpace(path) || string.IsNullOrWhiteSpace(name)) return string.Empty; - var tempPath = Path.Combine(path, name); - return File.Exists(tempPath) ? tempPath : string.Empty; - } - /// /// Executes the user-specified script. /// diff --git a/src/c#/GeneralUpdate.Core/Strategys/WindowsStrategy.cs b/src/c#/GeneralUpdate.Core/Strategys/WindowsStrategy.cs index 9c123154..6c43a61c 100644 --- a/src/c#/GeneralUpdate.Core/Strategys/WindowsStrategy.cs +++ b/src/c#/GeneralUpdate.Core/Strategys/WindowsStrategy.cs @@ -1,8 +1,5 @@ using System; using System.Diagnostics; -using System.IO; -using System.Runtime.InteropServices; -using System.Threading.Tasks; using GeneralUpdate.Common.FileBasic; using GeneralUpdate.Common.Internal; using GeneralUpdate.Common.Internal.Event; @@ -10,8 +7,6 @@ using GeneralUpdate.Common.Internal.Strategy; using GeneralUpdate.Common.Shared; using GeneralUpdate.Common.Shared.Object; -using GeneralUpdate.Common.Shared.Object.Enum; -using GeneralUpdate.Common.Shared.Service; using GeneralUpdate.Core.Pipeline; namespace GeneralUpdate.Core.Strategys @@ -21,83 +16,32 @@ namespace GeneralUpdate.Core.Strategys /// public class WindowsStrategy : AbstractStrategy { - private GlobalConfigInfo _configinfo = new(); - - public override void Create(GlobalConfigInfo parameter) => _configinfo = parameter; - - public override async Task ExecuteAsync() + protected override PipelineContext CreatePipelineContext(VersionInfo version, string patchPath) { - try + var context = base.CreatePipelineContext(version, patchPath); + + // Driver middleware (Windows-specific) + if (_configinfo.DriveEnabled == true) { - var status = ReportType.None; - var patchPath = StorageManager.GetTempDirectory(Patchs); - foreach (var version in _configinfo.UpdateVersions) - { - try - { - var context = new PipelineContext(); - //Common - context.Add("ZipFilePath", - Path.Combine(_configinfo.TempPath, $"{version.Name}{_configinfo.Format}")); - //Hash middleware - context.Add("Hash", version.Hash); - //Zip middleware - context.Add("Format", _configinfo.Format); - context.Add("Name", version.Name); - context.Add("Encoding", _configinfo.Encoding); - //Patch middleware - context.Add("SourcePath", _configinfo.InstallPath); - context.Add("PatchPath", patchPath); - context.Add("PatchEnabled", _configinfo.PatchEnabled); - //Driver middleware - if (_configinfo.DriveEnabled == true) - { - context.Add("DriverOutPut", StorageManager.GetTempDirectory("DriverOutPut")); - context.Add("FieldMappings", _configinfo.FieldMappings); - } - - var pipelineBuilder = new PipelineBuilder(context) - .UseMiddlewareIf(_configinfo.PatchEnabled) - .UseMiddleware() - .UseMiddleware() - .UseMiddlewareIf(_configinfo.DriveEnabled); - await pipelineBuilder.Build(); - status = ReportType.Success; - } - catch (Exception e) - { - status = ReportType.Failure; - GeneralTracer.Error( - "The Execute method in the GeneralUpdate.Core.WindowsStrategy class throws an exception.", - e); - EventManager.Instance.Dispatch(this, new ExceptionEventArgs(e, e.Message)); - } - finally - { - await VersionService.Report(_configinfo.ReportUrl - , version.RecordId - , status - , version.AppType - , _configinfo.Scheme - , _configinfo.Token); - } - } + context.Add("DriverOutPut", StorageManager.GetTempDirectory("DriverOutPut")); + context.Add("FieldMappings", _configinfo.FieldMappings); + } + + return context; + } - if (!string.IsNullOrEmpty(_configinfo.UpdateLogUrl)) - { - OpenBrowser(_configinfo.UpdateLogUrl); - } + protected override PipelineBuilder BuildPipeline(PipelineContext context) + { + return new PipelineBuilder(context) + .UseMiddlewareIf(_configinfo.PatchEnabled) + .UseMiddleware() + .UseMiddleware() + .UseMiddlewareIf(_configinfo.DriveEnabled); + } - Clear(patchPath); - Clear(_configinfo.TempPath); - StartApp(); - } - catch (Exception e) - { - GeneralTracer.Error( - "The Execute method in the GeneralUpdate.Core.WindowsStrategy class throws an exception.", e); - EventManager.Instance.Dispatch(this, new ExceptionEventArgs(e, e.Message)); - } + protected override void OnExecuteComplete() + { + StartApp(); } public override void StartApp() @@ -127,12 +71,5 @@ public override void StartApp() Process.GetCurrentProcess().Kill(); } } - - private string CheckPath(string path,string name) - { - if (string.IsNullOrWhiteSpace(path) || string.IsNullOrWhiteSpace(name)) return string.Empty; - var tempPath = Path.Combine(path, name); - return File.Exists(tempPath) ? tempPath : string.Empty; - } } } \ No newline at end of file