2026-02-04 08:58:36 +08:00
|
|
|
using FCPModUpdater.Commands.Settings;
|
|
|
|
|
using FCPModUpdater.Models;
|
|
|
|
|
using FCPModUpdater.Services;
|
|
|
|
|
using FCPModUpdater.UI;
|
2026-02-04 11:44:21 +08:00
|
|
|
using JetBrains.Annotations;
|
2026-02-04 08:58:36 +08:00
|
|
|
using Spectre.Console;
|
|
|
|
|
using Spectre.Console.Cli;
|
|
|
|
|
|
|
|
|
|
namespace FCPModUpdater.Commands;
|
|
|
|
|
|
2026-02-04 11:44:21 +08:00
|
|
|
[UsedImplicitly]
|
2026-04-08 14:14:33 +08:00
|
|
|
public class UpdateCommand(
|
|
|
|
|
IGitService gitService,
|
|
|
|
|
IModDiscoveryService modDiscoveryService,
|
|
|
|
|
UpdateCheckService updateCheckService) : AsyncCommand<ModPathSettings>
|
2026-02-04 08:58:36 +08:00
|
|
|
{
|
2026-03-12 06:54:31 +08:00
|
|
|
public static IReadOnlyList<InstalledMod> GetUpdateableMods(IReadOnlyList<InstalledMod> mods)
|
|
|
|
|
=> mods.Where(m => m.Source == ModSource.Git && m.Status == ModStatus.Behind).ToList();
|
|
|
|
|
|
2026-04-10 05:39:37 +08:00
|
|
|
protected override async Task<int> ExecuteAsync(CommandContext context, ModPathSettings settings,
|
|
|
|
|
CancellationToken ct)
|
2026-02-04 08:58:36 +08:00
|
|
|
{
|
|
|
|
|
try
|
|
|
|
|
{
|
2026-02-04 13:35:36 +08:00
|
|
|
var modsDirectory = ModsDirectoryResolver.Resolve(settings.ModDirectory?.FullName, interactive: false);
|
2026-02-04 08:58:36 +08:00
|
|
|
|
|
|
|
|
AnsiConsole.MarkupLine($"[grey]Using mods directory: {modsDirectory}[/]");
|
|
|
|
|
AnsiConsole.WriteLine();
|
|
|
|
|
|
2026-04-10 05:39:37 +08:00
|
|
|
Task<UpdateCheckResult?> updateCheckTask = updateCheckService.CheckForUpdateAsync(ct);
|
2026-02-10 18:30:04 +08:00
|
|
|
|
2026-02-04 08:58:36 +08:00
|
|
|
var mods = await ProgressReporter.WithStatusAsync(
|
|
|
|
|
"Scanning mods directory...",
|
2026-04-10 05:39:37 +08:00
|
|
|
async () => await modDiscoveryService.DiscoverModsAsync(modsDirectory, ct: ct));
|
2026-02-04 08:58:36 +08:00
|
|
|
|
2026-03-12 06:54:31 +08:00
|
|
|
var updateableMods = GetUpdateableMods(mods);
|
2026-02-04 08:58:36 +08:00
|
|
|
|
|
|
|
|
if (updateableMods.Count == 0)
|
|
|
|
|
{
|
|
|
|
|
AnsiConsole.MarkupLine("[green]All FCP mods are up to date![/]");
|
2026-05-22 17:52:43 +08:00
|
|
|
await RenderAppUpdateNoticeAsync(updateCheckTask);
|
2026-02-04 08:58:36 +08:00
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
AnsiConsole.MarkupLine($"[yellow]Found {updateableMods.Count} mod(s) with updates available:[/]");
|
2026-02-04 11:44:21 +08:00
|
|
|
foreach (InstalledMod mod in updateableMods)
|
2026-02-04 08:58:36 +08:00
|
|
|
{
|
|
|
|
|
AnsiConsole.MarkupLine($" • {mod.Name} [grey]({mod.CommitsBehind} commits behind)[/]");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
AnsiConsole.WriteLine();
|
|
|
|
|
|
|
|
|
|
var results = await ProgressReporter.WithBatchProgressAsync(
|
|
|
|
|
"Updating mods",
|
|
|
|
|
updateableMods,
|
2026-04-10 05:39:37 +08:00
|
|
|
installedMod => installedMod.Name,
|
2026-05-22 15:00:03 +08:00
|
|
|
async (mod, progress) => await GitModUpdater.UpdateAsync(gitService, mod, progress, ct));
|
2026-02-04 08:58:36 +08:00
|
|
|
|
|
|
|
|
ModTableRenderer.RenderUpdateSummary(results);
|
|
|
|
|
|
2026-05-22 17:52:43 +08:00
|
|
|
await RenderAppUpdateNoticeAsync(updateCheckTask);
|
2026-02-10 18:30:04 +08:00
|
|
|
|
2026-02-04 08:58:36 +08:00
|
|
|
var failCount = results.Count(r => !r.Success);
|
|
|
|
|
return failCount > 0 ? 1 : 0;
|
|
|
|
|
}
|
|
|
|
|
catch (OperationCanceledException)
|
|
|
|
|
{
|
|
|
|
|
AnsiConsole.MarkupLine("[grey]Operation cancelled.[/]");
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
{
|
|
|
|
|
AnsiConsole.WriteException(ex);
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
}
|
2026-05-22 17:52:43 +08:00
|
|
|
|
|
|
|
|
private static async Task RenderAppUpdateNoticeAsync(Task<UpdateCheckResult?> updateCheckTask)
|
|
|
|
|
{
|
|
|
|
|
UpdateCheckResult? updateResult = await updateCheckTask;
|
|
|
|
|
if (updateResult is null)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
AnsiConsole.WriteLine();
|
|
|
|
|
AppUpdateNoticeRenderer.Render(updateResult);
|
|
|
|
|
}
|
2026-02-04 08:58:36 +08:00
|
|
|
}
|