-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathProgram.cs
More file actions
88 lines (72 loc) · 3.33 KB
/
Program.cs
File metadata and controls
88 lines (72 loc) · 3.33 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
using Microsoft.Extensions.DependencyInjection;
using NextIteration.SpectreConsole.SelfUpdate;
using Spectre.Console;
using Spectre.Console.Cli;
internal sealed class Program
{
public static int Main(string[] args)
{
var services = new ServiceCollection();
services.AddSingleton<IAnsiConsole>(AnsiConsole.Console);
services.AddSelfUpdater(opts =>
{
opts.AppName = "selfupdate-demo";
// Replace with your repo. The HttpGitHubReleaseSource works for
// public repos out of the box; private repos can switch to
// GitHubTransport.GhCli or supply a token.
opts.UseGitHubReleases("StuartMeeks/NextIteration.SpectreConsole.SelfUpdate");
});
using var serviceProvider = services.BuildServiceProvider();
// 1. Sweep up the previous install (the running new binary is proof
// the last swap completed). Idempotent — safe to call every run.
// UpdateCleanup shows a status message while it works, but only when
// there's leftover .old/ or .update/ state to remove; otherwise it's
// silent.
UpdateCleanup.Run(serviceProvider);
// 2. Kick off the background "is there a new version?" probe. It's
// short-timeout and read-through-cached; on the warm path it
// resolves in microseconds.
var checkTask = UpdateBanner.KickOffCheck(serviceProvider);
// 3. Wire and run the CLI. The Spectre commands are already in DI —
// AddSelfUpdater registers UpdateCommand and UpdateCheckCommand
// so the TypeResolver can return them directly.
var app = new CommandApp(new ServiceProviderTypeRegistrar(serviceProvider));
app.Configure(config =>
{
config.SetApplicationName("selfupdate-demo");
config.AddUpdateCommand(); // exposes `selfupdate-demo update`
});
var exitCode = app.Run(args);
// 4. Render the banner if the probe came back positive. No-op when
// the network was slow or the user is already on the latest tag.
UpdateBanner.RenderIfAvailable(checkTask);
return exitCode;
}
}
/// <summary>
/// Trivial Spectre.Console.Cli registrar that delegates to a pre-built
/// MS DI <see cref="IServiceProvider"/>. Because every command is already
/// registered in DI by <c>AddSelfUpdater</c>, the Register* methods are
/// no-ops here.
/// </summary>
internal sealed class ServiceProviderTypeRegistrar : ITypeRegistrar
{
private readonly IServiceProvider _serviceProvider;
public ServiceProviderTypeRegistrar(IServiceProvider serviceProvider)
{
_serviceProvider = serviceProvider;
}
public ITypeResolver Build() => new ServiceProviderTypeResolver(_serviceProvider);
public void Register(Type service, Type implementation) { }
public void RegisterInstance(Type service, object implementation) { }
public void RegisterLazy(Type service, Func<object> factory) { }
}
internal sealed class ServiceProviderTypeResolver : ITypeResolver
{
private readonly IServiceProvider _serviceProvider;
public ServiceProviderTypeResolver(IServiceProvider serviceProvider)
{
_serviceProvider = serviceProvider;
}
public object? Resolve(Type? type) => type is null ? null : _serviceProvider.GetService(type);
}