|
| 1 | +using System.Collections.Concurrent; |
1 | 2 | using System.Diagnostics; |
2 | 3 | using System.Text; |
3 | 4 | using UniGetUI.Core.Classes; |
@@ -344,12 +345,53 @@ protected override async Task<OperationVeredict> PerformOperation() |
344 | 345 |
|
345 | 346 | if (!ShouldUseAgentBroker()) |
346 | 347 | { |
347 | | - return await base.PerformOperation(); |
| 348 | + if (!Package.Manager.Capabilities.SerializesOperations) |
| 349 | + return await base.PerformOperation(); |
| 350 | + |
| 351 | + SemaphoreSlim gate = ManagerOperationGates.GetOrAdd( |
| 352 | + Package.Manager.Name, |
| 353 | + _ => new SemaphoreSlim(1, 1) |
| 354 | + ); |
| 355 | + if (!await gate.WaitAsync(0)) |
| 356 | + { |
| 357 | + Line( |
| 358 | + CoreTools.Translate( |
| 359 | + "Waiting for another {0} operation to finish...", |
| 360 | + Package.Manager.DisplayName |
| 361 | + ), |
| 362 | + LineType.ProgressIndicator |
| 363 | + ); |
| 364 | + IsWaitingForManager = true; |
| 365 | + try |
| 366 | + { |
| 367 | + await gate.WaitAsync(CancellationToken); |
| 368 | + } |
| 369 | + catch (OperationCanceledException) |
| 370 | + { |
| 371 | + return OperationVeredict.Canceled; |
| 372 | + } |
| 373 | + finally |
| 374 | + { |
| 375 | + IsWaitingForManager = false; |
| 376 | + } |
| 377 | + } |
| 378 | + |
| 379 | + try |
| 380 | + { |
| 381 | + return await base.PerformOperation(); |
| 382 | + } |
| 383 | + finally |
| 384 | + { |
| 385 | + gate.Release(); |
| 386 | + } |
348 | 387 | } |
349 | 388 |
|
350 | 389 | return await PerformBrokerOperation(); |
351 | 390 | } |
352 | 391 |
|
| 392 | + private static readonly ConcurrentDictionary<string, SemaphoreSlim> ManagerOperationGates = |
| 393 | + new(); |
| 394 | + |
353 | 395 | /// <summary> |
354 | 396 | /// Determines whether this operation should be routed through the agent broker. |
355 | 397 | /// </summary> |
@@ -1058,6 +1100,7 @@ List<string> Output |
1058 | 1100 | ExplainNotApplicableUpdate(Output, ReturnCode); |
1059 | 1101 | ExplainInstallerHashMismatch(ReturnCode); |
1060 | 1102 | ExplainApplicationCurrentlyRunning(Output, ReturnCode); |
| 1103 | + ExplainFileInUse(Output); |
1061 | 1104 | } |
1062 | 1105 |
|
1063 | 1106 | return Task.FromResult(veredict); |
@@ -1197,6 +1240,17 @@ private void ExplainApplicationCurrentlyRunning(List<string> output, int returnC |
1197 | 1240 | #endif |
1198 | 1241 | } |
1199 | 1242 |
|
| 1243 | + private void ExplainFileInUse(List<string> output) |
| 1244 | + { |
| 1245 | + if (!output.Any(line => line.Contains("[WinError 32]", StringComparison.Ordinal))) |
| 1246 | + return; |
| 1247 | + |
| 1248 | + Metadata.FailureMessage = CoreTools.Translate( |
| 1249 | + "A file of {package} is in use by another program. Close any program that may be using it, then try again", |
| 1250 | + new Dictionary<string, object?> { { "package", Package.Name } } |
| 1251 | + ); |
| 1252 | + } |
| 1253 | + |
1200 | 1254 | private void ExplainNotApplicableUpdate(List<string> output, int returnCode) |
1201 | 1255 | { |
1202 | 1256 | #if WINDOWS |
|
0 commit comments