chore(dependencies): Upgrade dependencies

This commit brings the dependencies up to date.

This more importantly brings the stable version of system.commandline
and all the changes needed to make it work properly with the program.

Importantly this changes how validation is done, and how defaults are
passed to commandline. This also allows me to remove the original null
protection as when the argument is not specified commandline defaults to
the current directory.

This has also meant I can remove unnecessary async calls that appear to
have no performance benefits, and remove some null checking that isn't
needed any more.
This commit is contained in:
Robert Morrison 2026-01-03 04:00:54 +00:00
parent 9fe53b344a
commit 700dc715fb
Signed by: robert
GPG Key ID: 73E012EB3F4EC696
2 changed files with 42 additions and 59 deletions

View File

@ -17,8 +17,6 @@
*/
using Serilog;
using System.CommandLine.Builder;
using System.CommandLine.Parsing;
using System.CommandLine;
using System.Diagnostics;
using System.Reflection;
@ -66,70 +64,59 @@ class Program
Stopwatch TotalExecutionTime = Stopwatch.StartNew();
/* !! IMPORTANT !!
WARN:
This code uses system.commandline which is still in pre-release
/* WARN:
This code uses system.commandline
the following section of code will contain comments to explain the intent of the programmer
which may be useful if system.commandline has breaking changes
*/
// First the option for the project directory is created
var ProjectDirectoryOption = new Option<DirectoryInfo>(
name: "--project",
description: "The Directory for the project");
ProjectDirectoryOption.IsRequired = false; // it is not required as not providing it infers that the current directory is the project directory
// If the option is used then the input is validated before control passes to any of the actual code.
ProjectDirectoryOption.AddValidator(result =>
Option<DirectoryInfo> ProjectDirectoryOption = new("--project","-p")
{
Description = "The directory of the project",
Required = false,
DefaultValueFactory = _ =>
{
if (!result.GetValueForOption(ProjectDirectoryOption)!.Exists)
{
result.ErrorMessage = $"Project directory {result.GetValueForOption(ProjectDirectoryOption)} does not exist.";
}
return new DirectoryInfo(Directory.GetCurrentDirectory());
}
);
};
// Add a validator as we want the directory to exist.
ProjectDirectoryOption.Validators.Add(result =>
{
if (! result.GetValue(ProjectDirectoryOption)!.Exists)
{
result.AddError($"Directory {result.GetValue(ProjectDirectoryOption)} does not exist");
Log.Fatal($"Passed directory '{result.GetValue(ProjectDirectoryOption)}' does not exist");
}
});
// The root command is the entry point for commandline but otherwise does nothing.
var rootCommand = new RootCommand("csSiteGen");
// TODO: Verify if the use of async in these functions is necessary
RootCommand rootCommand = new("csSiteGen");
// This creates the command for cleaning a projects output directory.
var cleanCommand = new Command("clean", "Clean the projects output directory");
cleanCommand.AddOption(ProjectDirectoryOption); // This command can use the project directory option we created earlier
cleanCommand.SetHandler(async (ProjectDirectory) =>
cleanCommand.Options.Add(ProjectDirectoryOption); // This command can use the project directory option we created earlier
cleanCommand.SetAction(parseResult =>
{
await Task.Run(() =>
{
Clean(ProjectDirectory);
});
},ProjectDirectoryOption);
Clean(parseResult.GetValue<DirectoryInfo>("--project")!);
});
// This creates the command for actually converting the project.
var convertCommand = new Command("convert", "Convert the projects input directory and place the files in the output directory.");
convertCommand.AddOption(ProjectDirectoryOption); // This command can use the project directory option
convertCommand.SetHandler(async (ProjectDirectory) =>
convertCommand.Options.Add(ProjectDirectoryOption); // This command can use the project directory option
convertCommand.SetAction(parseResult =>
{
await Task.Run(() =>
{
Convert(ProjectDirectory);
});
},ProjectDirectoryOption);
Convert(parseResult.GetValue<DirectoryInfo>("--project")!);
});
// Adding the commands to the root command makes them actually callable on the commandline
rootCommand.AddCommand(cleanCommand);
rootCommand.AddCommand(convertCommand);
// The parser is what actually handles the arguments and dispatches them to the appropriate commands.
// This is used instead of the simpler method of just Invoking the root command as it automatically creates usage statements.
// It also makes a user aware that a subcommand needs to be used.
var parser = new CommandLineBuilder(rootCommand)
.UseDefaults()
.Build();
parser.Invoke(args);
rootCommand.Subcommands.Add(cleanCommand);
rootCommand.Subcommands.Add(convertCommand);
// Parse the commandline and immediately execute.
rootCommand.Parse(args).Invoke();
TotalExecutionTime.Stop();
Log.Information("TotalExecutionTime {time:000}ms", TotalExecutionTime.ElapsedMilliseconds);
@ -139,12 +126,12 @@ class Program
return 0;
}
static int Convert(DirectoryInfo? ProjectDirectory)
static int Convert(DirectoryInfo ProjectDirectory)
{
Log.Information("Convert command was called, beginning conversion.");
// WARN: This is only temporary as Spectre.Console does not recognise some Linux terminals
// A better solution that checks the terminal value and sets this option should be added in the future.
// TODO: A better solution that checks the terminal value and sets this option should be added in the future.
AnsiConsole.Console.Profile.Capabilities.Ansi = true;
@ -211,7 +198,7 @@ class Program
return 0;
}
static int Clean(DirectoryInfo? ProjectDirectory)
static int Clean(DirectoryInfo ProjectDirectory)
{
Log.Information("Clean command was called, Beginning cleaning");
@ -283,15 +270,10 @@ class Program
}
static ProjectSettings GetProjectSettings(DirectoryInfo? ProjectDirectory)
static ProjectSettings GetProjectSettings(DirectoryInfo ProjectDirectory)
{
// TODO: implement proper error handling where file access is performed.
if (ProjectDirectory is null)
{
// use the current directory if no project directory is passed.
ProjectDirectory = new DirectoryInfo(".");
}
Log.Information("{projectdir} => fullname {pdfn}",ProjectDirectory, ProjectDirectory.FullName);
FileInfo projectFile = new (Path.Combine(ProjectDirectory.FullName,"cssitegen.json"));
@ -299,6 +281,7 @@ class Program
if (!projectFile.Exists)
{
Log.Fatal("Cannot locate project file {pf} in {dir}",projectFile,ProjectDirectory);
AnsiConsole.MarkupLineInterpolated($"[red]No project file found in [yellow]{ProjectDirectory}[/][/]");
Environment.Exit(1);
}

View File

@ -16,11 +16,11 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Serilog" Version="4.0.0" />
<PackageReference Include="Serilog.Sinks.Console" Version="5.0.1" />
<PackageReference Include="Serilog.Sinks.File" Version="5.0.0" />
<PackageReference Include="spectre.console" Version="0.49.1" />
<PackageReference Include="system.commandline" Version="2.0.0-beta4.22272.1" />
<PackageReference Include="Serilog" Version="4.3.0" />
<PackageReference Include="Serilog.Sinks.Console" Version="6.1.1" />
<PackageReference Include="Serilog.Sinks.File" Version="7.0.0" />
<PackageReference Include="spectre.console" Version="0.54.0" />
<PackageReference Include="system.commandline" Version="2.0.1" />
</ItemGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">