Skip to content

Commit d3dcd74

Browse files
committed
fix: resolve merge conflict in MacStrategy.cs
2 parents b644c4b + 2e85a73 commit d3dcd74

12 files changed

Lines changed: 136 additions & 62 deletions

File tree

ipc/BOWL_TEST_ENV_VAR.enc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
�j{N��;qm�8�

src/c#/GeneralUpdate.Core/Bootstrap/GeneralUpdateBootstrap.cs

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
using GeneralUpdate.Core.Hooks;
1919
using GeneralUpdate.Core.Ipc;
2020
using GeneralUpdate.Core.Download.Reporting;
21+
using GeneralUpdate.Core.Differential;
2122

2223
namespace GeneralUpdate.Core;
2324

@@ -130,6 +131,17 @@ private async Task<GeneralUpdateBootstrap> LaunchWithStrategy(IStrategy roleStra
130131

131132
roleStrategy.Create(_configInfo);
132133

134+
// Inject binary differ into OS-level strategy for differential patching
135+
// Must be called after Create() since _osStrategy is initialized there.
136+
var differ = ResolveExtension<IBinaryDiffer>();
137+
if (differ != null)
138+
{
139+
if (roleStrategy is ClientUpdateStrategy cs2)
140+
cs2.SetDiffer(differ);
141+
else if (roleStrategy is UpgradeUpdateStrategy us2)
142+
us2.SetDiffer(differ);
143+
}
144+
133145
// Check custom skip condition before executing update
134146
if (_customSkipOption?.Invoke() == true)
135147
{
@@ -161,8 +173,9 @@ private async Task<GeneralUpdateBootstrap> LaunchWithStrategy(IStrategy roleStra
161173
// ════════════════════════════════════════════════════════════════
162174

163175
public GeneralUpdateBootstrap SetConfig(Configinfo configInfo)
164-
{
165-
_configInfo = ConfigurationMapper.MapToGlobalConfigInfo(configInfo);
176+
{
177+
configInfo.Validate();
178+
_configInfo = ConfigurationMapper.MapToGlobalConfigInfo(configInfo);
166179

167180
var appType = GetOption(UpdateOptions.AppType);
168181
if (appType != AppType.Upgrade)

src/c#/GeneralUpdate.Core/Configuration/GlobalConfigInfo.cs

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -95,10 +95,6 @@ public class GlobalConfigInfo : BaseConfigInfo
9595
/// </summary>
9696
public string ProcessInfo { get; set; }
9797

98-
/// <summary>
99-
/// Directory path containing driver files for update.
100-
/// Used when DriveEnabled is true to locate driver files for installation.
101-
/// </summary>
10298
/// <summary>
10399
/// Indicates whether differential patch update is enabled.
104100
/// Computed from UpdateOption.Patch or defaults to true.

src/c#/GeneralUpdate.Core/Download/Orchestrators/DefaultDownloadOrchestrator.cs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,16 @@ public async Task<DownloadReport> ExecuteAsync(
6767

6868
var tasks = plan.Assets.Select(async asset =>
6969
{
70-
await sem.WaitAsync(token).ConfigureAwait(false);
70+
var acquired = await sem.WaitAsync(TimeSpan.FromMinutes(5), token).ConfigureAwait(false);
71+
if (!acquired)
72+
{
73+
GeneralTracer.Warn("DefaultDownloadOrchestrator: semaphore wait timed out for " + asset.Name + ", skipping.");
74+
lock (results)
75+
{
76+
results.Add(new DownloadResult(asset, null, 0, TimeSpan.Zero, 0, false, "Semaphore wait timed out"));
77+
}
78+
return;
79+
}
7180
try
7281
{
7382
var fileName = GetFileName(asset);

src/c#/GeneralUpdate.Core/FileSystem/StorageManager.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ public static void CreateJson<T>(string targetPath, T obj, JsonTypeInfo<T>? type
8282

8383
public static string GetTempDirectory(string name)
8484
{
85-
var path = $"generalupdate_{DateTime.Now:yyyy-MM-dd}_{name}";
85+
var path = $"generalupdate_{DateTime.Now:yyyy-MM-dd-HHmmss-fff}_{System.Diagnostics.Process.GetCurrentProcess().Id}_{name}";
8686
var tempDir = Path.Combine(Path.GetTempPath(), path);
8787
if (!Directory.Exists(tempDir))
8888
{

src/c#/GeneralUpdate.Core/Pipeline/PatchMiddleware.cs

Lines changed: 8 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -10,29 +10,22 @@ namespace GeneralUpdate.Core.Pipeline;
1010
/// Differential patch middleware. Applies binary patches (BSDIFF, HDiffPatch, etc.)
1111
/// to bring files from an old version to a new version.
1212
///
13-
/// The <see cref="IBinaryDiffer"/> implementation is injected via
13+
/// The <see cref="IBinaryDiffer"/> implementation is resolved from
14+
/// <see cref="PipelineContext"/> (key "BinaryDiffer"), set by
15+
/// <see cref="GeneralUpdate.Core.Strategy.AbstractStrategy"/> when the differ is injected via
1416
/// <c>Bootstrap.BinaryDiffer&lt;T&gt;()</c>. Without injection, patches are skipped.
1517
/// </summary>
1618
public class PatchMiddleware : IMiddleware
1719
{
18-
private readonly IBinaryDiffer? _differ;
19-
20-
/// <summary>Parameterless constructor (required by PipelineBuilder). Uses no differ.</summary>
21-
public PatchMiddleware() { }
22-
23-
/// <summary>Creates a PatchMiddleware with an optional differ.</summary>
24-
/// <param name="differ">Binary differ implementation. If null, patches are skipped.</param>
25-
public PatchMiddleware(IBinaryDiffer? differ)
26-
{
27-
_differ = differ;
28-
}
29-
3020
public async Task InvokeAsync(PipelineContext context)
3121
{
3222
var sourcePath = context.Get<string>("SourcePath");
3323
var targetPath = context.Get<string>("PatchPath");
3424

35-
if (_differ == null)
25+
// Resolve differ from pipeline context (injected via AbstractStrategy)
26+
var differ = context.Get<IBinaryDiffer>("BinaryDiffer");
27+
28+
if (differ == null)
3629
{
3730
GeneralTracer.Info("PatchMiddleware.InvokeAsync: no IBinaryDiffer injected — patch skipped. " +
3831
"Use Bootstrap.BinaryDiffer<T>() to enable differential patching.");
@@ -42,7 +35,7 @@ public async Task InvokeAsync(PipelineContext context)
4235
GeneralTracer.Info($"PatchMiddleware.InvokeAsync: applying differential patch. SourcePath={sourcePath}, PatchPath={targetPath}");
4336
try
4437
{
45-
await _differ.DirtyAsync(sourcePath, targetPath, targetPath);
38+
await differ.DirtyAsync(sourcePath, targetPath, targetPath);
4639
GeneralTracer.Info("PatchMiddleware.InvokeAsync: differential patch applied successfully.");
4740
}
4841
catch (Exception ex)

src/c#/GeneralUpdate.Core/Strategy/AbstractStrategy.cs

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
using System;
22
using System.IO;
33
using System.Threading.Tasks;
4+
using GeneralUpdate.Core.Differential;
45
using GeneralUpdate.Core.FileSystem;
56
using GeneralUpdate.Core.Event;
67
using GeneralUpdate.Core.Pipeline;
@@ -22,6 +23,9 @@ public abstract class AbstractStrategy : IStrategy
2223

2324
/// <summary>Optional reporter for update status reporting.</summary>
2425
protected IUpdateReporter? Reporter { get; set; }
26+
27+
/// <summary>Optional binary differ for differential patch updates.</summary>
28+
public IBinaryDiffer? Differ { get; set; }
2529

2630
public virtual void Execute() => throw new NotImplementedException();
2731

@@ -46,6 +50,7 @@ public virtual async Task ExecuteAsync()
4650
{
4751
status = ReportType.Failure;
4852
HandleExecuteException(e);
53+
TryRollback();
4954
}
5055
finally
5156
{
@@ -89,6 +94,8 @@ protected virtual PipelineContext CreatePipelineContext(VersionInfo version, str
8994
context.Add("SourcePath", _configinfo.InstallPath);
9095
context.Add("PatchPath", patchPath);
9196
context.Add("PatchEnabled", _configinfo.PatchEnabled);
97+
// Binary differ for differential patching
98+
context.Add("BinaryDiffer", Differ);
9299

93100
return context;
94101
}
@@ -135,10 +142,32 @@ protected static string CheckPath(string path, string name)
135142
// The Hooks and Reporter properties are declared here so subclasses inherit them
136143
// without redeclaring.
137144

145+
/// <summary>
146+
/// Attempts to restore from backup when a pipeline execution fails.
147+
/// Only restores if a backup directory exists for the current version.
148+
/// </summary>
149+
private void TryRollback()
150+
{
151+
try
152+
{
153+
var backupDir = _configinfo.BackupDirectory;
154+
if (!string.IsNullOrWhiteSpace(backupDir) && Directory.Exists(backupDir))
155+
{
156+
GeneralTracer.Warn($"AbstractStrategy.TryRollback: restoring from backup {backupDir} -> {_configinfo.InstallPath}");
157+
StorageManager.Restore(backupDir, _configinfo.InstallPath);
158+
GeneralTracer.Info("AbstractStrategy.TryRollback: restore completed.");
159+
}
160+
}
161+
catch (Exception ex)
162+
{
163+
GeneralTracer.Error("AbstractStrategy.TryRollback: rollback failed.", ex);
164+
}
165+
}
166+
138167
private static void Clear(string path)
139168
{
140169
if (Directory.Exists(path))
141170
StorageManager.DeleteDirectory(path);
142171
}
143172
}
144-
}
173+
}

src/c#/GeneralUpdate.Core/Strategy/ClientUpdateStrategy.cs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,8 @@ public void Create(GlobalConfigInfo parameter)
4646
{
4747
_configInfo = parameter ?? throw new ArgumentNullException(nameof(parameter));
4848
_osStrategy = ResolveOsStrategy();
49+
if (_pendingDiffer != null && _osStrategy is AbstractStrategy abs)
50+
abs.Differ = _pendingDiffer;
4951
}
5052

5153
public async Task ExecuteAsync()
@@ -73,6 +75,18 @@ public void Execute()
7375
ExecuteAsync().GetAwaiter().GetResult();
7476
}
7577

78+
private Differential.IBinaryDiffer? _pendingDiffer;
79+
80+
/// <summary>Sets the binary differ on the underlying OS-level strategy for differential patch updates.
81+
/// Safe to call before or after Create(). If called before, the differ is cached and applied when Create() resolves _osStrategy.</summary>
82+
public void SetDiffer(Differential.IBinaryDiffer? differ)
83+
{
84+
if (_osStrategy is AbstractStrategy abs)
85+
abs.Differ = differ;
86+
else
87+
_pendingDiffer = differ;
88+
}
89+
7690
public void StartApp()
7791
{
7892
_osStrategy?.StartApp();

src/c#/GeneralUpdate.Core/Strategy/MacStrategy.cs

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -21,21 +21,36 @@ public override async Task ExecuteAsync()
2121

2222
public override void StartApp()
2323
{
24-
var mainApp = Path.Combine(
25-
_configinfo.InstallPath ?? string.Empty,
26-
_configinfo.MainAppName ?? string.Empty);
24+
try
25+
{
26+
var mainApp = Path.Combine(
27+
_configinfo.InstallPath ?? string.Empty,
28+
_configinfo.MainAppName ?? string.Empty);
2729

28-
if (!string.IsNullOrEmpty(_configinfo.MainAppName) && File.Exists(mainApp))
30+
if (!string.IsNullOrEmpty(_configinfo.MainAppName) && File.Exists(mainApp))
31+
{
32+
GeneralTracer.Info($"MacStrategy: starting {mainApp}");
33+
System.Diagnostics.Process.Start(mainApp);
34+
}
35+
}
36+
catch (Exception e)
37+
{
38+
GeneralTracer.Error("The StartApp method in MacStrategy threw an exception.", e);
39+
EventManager.Instance.Dispatch(this, new ExceptionEventArgs(e, e.Message));
40+
}
41+
finally
2942
{
30-
GeneralTracer.Info($"MacStrategy: starting {mainApp}");
31-
System.Diagnostics.Process.Start(mainApp);
43+
GeneralTracer.Info("MacStrategy.StartApp: releasing tracer and terminating updater process.");
44+
GeneralTracer.Dispose();
45+
GracefulExit.CurrentProcessAsync().GetAwaiter().GetResult();
3246
}
3347
}
3448

3549
public override void Create(GlobalConfigInfo configInfo) => _configinfo = configInfo;
3650

3751
protected override PipelineBuilder BuildPipeline(PipelineContext context)
3852
{
53+
GeneralTracer.Info($"MacStrategy.BuildPipeline: assembling middleware pipeline. PatchEnabled={_configinfo.PatchEnabled}");
3954
var builder = new PipelineBuilder(context)
4055
.UseMiddleware<HashMiddleware>()
4156
.UseMiddleware<CompressMiddleware>()

src/c#/GeneralUpdate.Core/Strategy/OSSUpdateStrategy.cs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -189,7 +189,11 @@ private async Task ExecuteUpgradeAsync()
189189
await SafeOnUpdateErrorAsync(ctx, ex).ConfigureAwait(false);
190190
await SafeReportUpdateFailedAsync(ctx, ex).ConfigureAwait(false);
191191
GeneralTracer.Error("OSSUpdateStrategy.ExecuteUpgradeAsync failed.", ex);
192-
throw;
192+
GeneralUpdate.Core.Event.EventManager.Instance.Dispatch(this, new GeneralUpdate.Core.Event.ExceptionEventArgs(ex, ex.Message));
193+
}
194+
finally
195+
{
196+
await GracefulExit.CurrentProcessAsync().ConfigureAwait(false);
193197
}
194198
}
195199

0 commit comments

Comments
 (0)