fix: switch from RootCommand to Command to handle stripped executables

This commit is contained in:
Dylan R. E. Moonfire 2021-11-29 00:54:17 -06:00
parent 6b03ca4c28
commit e5e87770f9
6 changed files with 41 additions and 9 deletions

View file

@ -13,7 +13,15 @@ namespace MfGames.ToolBuilder
string[] arguments,
TType defaultValue)
{
var rootCommand = new RootCommand
// Normally, we should be using `RootCommand` here because it does
// the "right" thing with regards to picking up the executable name
// and path from the environment. However, it appears when the
// library/executable is stripped, it blows up. So we use Command
// directly and fake the RootCommand.
//
// We don't need a "real" executable name here, so we just hard-code
// a faked one.
var rootCommand = new Command("_executable", string.Empty)
{
option,
};

View file

@ -78,7 +78,7 @@ namespace MfGames.ToolBuilder.Globals
/// Adds the common options to the command.
/// </summary>
/// <param name="root"></param>
public void AddOptions(RootCommand root)
public void AddOptions(Command root)
{
root.AddGlobalOption(this.ConfigOption);
}

View file

@ -34,7 +34,7 @@ namespace MfGames.ToolBuilder.Globals
/// Adds the common options to the command.
/// </summary>
/// <param name="root"></param>
public void AddOptions(RootCommand root)
public void AddOptions(Command root)
{
root.AddGlobalOption(this.LogLevelOption);
}

View file

@ -410,6 +410,8 @@ namespace MfGames.ToolBuilder.Tables
// Default is mostly like ConsoleTableExt but there is a separator
// between the headers because it makes it harder to parse.
builder
.WithPaddingLeft(string.Empty)
.WithPaddingRight(string.Empty)
.WithCharMapDefinition(
new Dictionary<CharMapPositions, char>
{
@ -418,7 +420,7 @@ namespace MfGames.ToolBuilder.Tables
.WithHeaderCharMapDefinition(
new Dictionary<HeaderCharMapPositions, char>
{
{ HeaderCharMapPositions.BottomCenter, '+' },
{ HeaderCharMapPositions.BottomCenter, ' ' },
{ HeaderCharMapPositions.Divider, ' ' },
{ HeaderCharMapPositions.BorderBottom, '-' },
});

View file

@ -165,6 +165,12 @@ namespace MfGames.ToolBuilder
.AsSelf()
.SingleInstance();
// Register the tool service since we have to use the factory to
// use it.
builder
.Register(this.CreateToolService)
.SingleInstance();
// Register the components required to make the CLI work.
builder.RegisterModule<ToolBuilderModule>();
}
@ -174,7 +180,14 @@ namespace MfGames.ToolBuilder
IServiceCollection services)
{
services.AddAutofac();
services.AddHostedService<ToolService>();
}
private ToolService CreateToolService(IComponentContext context)
{
var factory = context.Resolve<ToolService.Factory>();
var service = factory(this.InternalName);
return service;
}
}
}

View file

@ -25,6 +25,8 @@ namespace MfGames.ToolBuilder
/// </summary>
public class ToolService : IHostedService
{
private readonly string cliName;
private readonly IList<ITopCommand> commands;
private readonly ConfigToolGlobalService configService;
@ -36,12 +38,15 @@ namespace MfGames.ToolBuilder
private readonly LoggingToolGlobalService loggingService;
public ToolService(
string cliName,
ILogger logger,
IHostApplicationLifetime lifetime,
IList<ITopCommand> commands,
ConfigToolGlobalService configService,
LoggingToolGlobalService loggingService)
{
this.cliName = cliName
?? throw new ArgumentNullException(nameof(cliName));
this.lifetime = lifetime;
this.commands = commands;
this.configService = configService;
@ -49,6 +54,8 @@ namespace MfGames.ToolBuilder
this.logger = logger.ForContext<ToolService>();
}
public delegate ToolService Factory(string cliName);
/// <inheritdoc />
public Task StartAsync(CancellationToken cancellationToken)
{
@ -71,11 +78,13 @@ namespace MfGames.ToolBuilder
return Task.CompletedTask;
}
private RootCommand CreateRootCommand()
private Command CreateRootCommand()
{
// Create the root command and add in the top-level commands
// underneath it.
var root = new RootCommand();
// underneath it. We can't use the "real" `RootCommand` here because
// it doesn't work in stripped executables (because this is a
// library) so we fake it with a "normal" command.
var root = new Command(this.cliName, string.Empty);
foreach (var command in this.commands)
{
@ -116,7 +125,7 @@ namespace MfGames.ToolBuilder
try
{
// Build the command tree.
RootCommand root = this.CreateRootCommand();
Command root = this.CreateRootCommand();
string[] args = Environment.GetCommandLineArgs();
// Execute the command.