Skip to content

Commit

Permalink
Merge multiple-files into master.
Browse files Browse the repository at this point in the history
  • Loading branch information
bgrainger committed Feb 13, 2025
2 parents d081351 + f20b5be commit d028616
Show file tree
Hide file tree
Showing 5 changed files with 49 additions and 46 deletions.
12 changes: 6 additions & 6 deletions src/Sign.Cli/AzureKeyVaultCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ internal sealed class AzureKeyVaultCommand : Command
internal Option<string> CertificateOption { get; } = new(["--azure-key-vault-certificate", "-kvc"], AzureKeyVaultResources.CertificateOptionDescription);
internal AzureCredentialOptions AzureCredentialOptions { get; } = new();

internal Argument<string?> FileArgument { get; } = new("file(s)", Resources.FilesArgumentDescription);
internal Argument<List<string>?> FilesArgument { get; } = new("file(s)", Resources.FilesArgumentDescription) { Arity = ArgumentArity.OneOrMore };

internal AzureKeyVaultCommand(CodeCommand codeCommand, IServiceProviderFactory serviceProviderFactory)
: base("azure-key-vault", AzureKeyVaultResources.CommandDescription)
Expand All @@ -32,13 +32,13 @@ internal AzureKeyVaultCommand(CodeCommand codeCommand, IServiceProviderFactory s
AddOption(CertificateOption);
AzureCredentialOptions.AddOptionsToCommand(this);

AddArgument(FileArgument);
AddArgument(FilesArgument);

this.SetHandler(async (InvocationContext context) =>
{
string? fileArgument = context.ParseResult.GetValueForArgument(FileArgument);
List<string>? filesArgument = context.ParseResult.GetValueForArgument(FilesArgument);

if (string.IsNullOrEmpty(fileArgument))
if (filesArgument is not { Count: > 0 })
{
context.Console.Error.WriteLine(Resources.MissingFileValue);
context.ExitCode = ExitCode.InvalidOptions;
Expand All @@ -47,7 +47,7 @@ internal AzureKeyVaultCommand(CodeCommand codeCommand, IServiceProviderFactory s

// this check exists as a courtesy to users who may have been signing .clickonce files via the old workaround.
// at some point we should remove this check, probably once we hit v1.0
if (fileArgument.EndsWith(".clickonce", StringComparison.OrdinalIgnoreCase))
if (filesArgument.Any(x => x.EndsWith(".clickonce", StringComparison.OrdinalIgnoreCase)))
{
context.Console.Error.WriteLine(AzureKeyVaultResources.ClickOnceExtensionNotSupported);
context.ExitCode = ExitCode.InvalidOptions;
Expand All @@ -66,7 +66,7 @@ internal AzureKeyVaultCommand(CodeCommand codeCommand, IServiceProviderFactory s
string certificateId = context.ParseResult.GetValueForOption(CertificateOption)!;

KeyVaultServiceProvider keyVaultServiceProvider = new(credential, url, certificateId);
await codeCommand.HandleAsync(context, serviceProviderFactory, keyVaultServiceProvider, fileArgument);
await codeCommand.HandleAsync(context, serviceProviderFactory, keyVaultServiceProvider, filesArgument);
});
}
}
Expand Down
10 changes: 5 additions & 5 deletions src/Sign.Cli/CertificateStoreCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ internal sealed class CertificateStoreCommand : Command
internal Option<bool> UseMachineKeyContainerOption { get; } = new(["--use-machine-key-container", "-km"], getDefaultValue: () => false, description: CertificateStoreResources.UseMachineKeyContainerOptionDescription);
internal Option<bool> InteractiveOption { get; } = new(["--interactive", "-i"], getDefaultValue: () => false, description: CertificateStoreResources.InteractiveDescription);

internal Argument<string?> FileArgument { get; } = new("file(s)", Resources.FilesArgumentDescription);
internal Argument<List<string>?> FilesArgument { get; } = new("file(s)", Resources.FilesArgumentDescription) { Arity = ArgumentArity.OneOrMore };

internal CertificateStoreCommand(CodeCommand codeCommand, IServiceProviderFactory serviceProviderFactory)
: base("certificate-store", Resources.CertificateStoreCommandDescription)
Expand All @@ -40,13 +40,13 @@ internal CertificateStoreCommand(CodeCommand codeCommand, IServiceProviderFactor
AddOption(PrivateKeyContainerOption);
AddOption(UseMachineKeyContainerOption);
AddOption(InteractiveOption);
AddArgument(FileArgument);
AddArgument(FilesArgument);

this.SetHandler(async (InvocationContext context) =>
{
string? fileArgument = context.ParseResult.GetValueForArgument(FileArgument);
List<string>? filesArgument = context.ParseResult.GetValueForArgument(FilesArgument);

if (string.IsNullOrEmpty(fileArgument))
if (filesArgument is not { Count: > 0 })
{
context.Console.Error.WriteLine(Resources.MissingFileValue);
context.ExitCode = ExitCode.InvalidOptions;
Expand Down Expand Up @@ -111,7 +111,7 @@ internal CertificateStoreCommand(CodeCommand codeCommand, IServiceProviderFactor
useMachineKeyContainer,
isInteractive);

await codeCommand.HandleAsync(context, serviceProviderFactory, certificateStoreServiceProvider, fileArgument);
await codeCommand.HandleAsync(context, serviceProviderFactory, certificateStoreServiceProvider, filesArgument);
});
}

Expand Down
61 changes: 32 additions & 29 deletions src/Sign.Cli/CodeCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ internal CodeCommand()
AddGlobalOption(VerbosityOption);
}

internal async Task HandleAsync(InvocationContext context, IServiceProviderFactory serviceProviderFactory, ISignatureProvider signatureProvider, string fileArgument)
internal async Task HandleAsync(InvocationContext context, IServiceProviderFactory serviceProviderFactory, ISignatureProvider signatureProvider, IEnumerable<string> filesArgument)
{
// Some of the options have a default value and that is why we can safely use
// the null-forgiving operator (!) to simplify the code.
Expand Down Expand Up @@ -95,44 +95,47 @@ internal async Task HandleAsync(InvocationContext context, IServiceProviderFacto
(IServiceProvider serviceProvider) => signatureProvider.GetCertificateProvider(serviceProvider));
});

List<FileInfo> inputFiles;
List<FileInfo> inputFiles = [];

// If we're going to glob, we can't be fully rooted currently (fix me later)
bool isGlob = fileArgument.Contains('*');

if (isGlob)
foreach (var fileArgument in filesArgument)
{
if (Path.IsPathRooted(fileArgument))
// If we're going to glob, we can't be fully rooted currently (fix me later)
bool isGlob = fileArgument.Contains('*');

if (isGlob)
{
context.Console.Error.WriteLine(Resources.InvalidFileValue);
context.ExitCode = ExitCode.InvalidOptions;
return;
}
if (Path.IsPathRooted(fileArgument))
{
context.Console.Error.WriteLine(Resources.InvalidFileValue);
context.ExitCode = ExitCode.InvalidOptions;
return;
}

IFileListReader fileListReader = serviceProvider.GetRequiredService<IFileListReader>();
IFileMatcher fileMatcher = serviceProvider.GetRequiredService<IFileMatcher>();
IFileListReader fileListReader = serviceProvider.GetRequiredService<IFileListReader>();
IFileMatcher fileMatcher = serviceProvider.GetRequiredService<IFileMatcher>();

using (MemoryStream stream = new(Encoding.UTF8.GetBytes(fileArgument)))
using (StreamReader reader = new(stream))
{
fileListReader.Read(reader, out Matcher? matcher, out Matcher? antiMatcher);
using (MemoryStream stream = new(Encoding.UTF8.GetBytes(fileArgument)))
using (StreamReader reader = new(stream))
{
fileListReader.Read(reader, out Matcher? matcher, out Matcher? antiMatcher);

DirectoryInfoBase directory = new DirectoryInfoWrapper(baseDirectory);
DirectoryInfoBase directory = new DirectoryInfoWrapper(baseDirectory);

IEnumerable<FileInfo> matches = fileMatcher.EnumerateMatches(directory, matcher);
IEnumerable<FileInfo> matches = fileMatcher.EnumerateMatches(directory, matcher);

if (antiMatcher is not null)
{
IEnumerable<FileInfo> antiMatches = fileMatcher.EnumerateMatches(directory, antiMatcher);
matches = matches.Except(antiMatches, FileInfoComparer.Instance);
}
if (antiMatcher is not null)
{
IEnumerable<FileInfo> antiMatches = fileMatcher.EnumerateMatches(directory, antiMatcher);
matches = matches.Except(antiMatches, FileInfoComparer.Instance);
}

inputFiles = matches.ToList();
inputFiles.AddRange(matches);
}
}
else
{
inputFiles.Add(new FileInfo(ExpandFilePath(baseDirectory, fileArgument)));
}
}
else
{
inputFiles = [new FileInfo(ExpandFilePath(baseDirectory, fileArgument))];
}

FileInfo? fileList = null;
Expand Down
10 changes: 5 additions & 5 deletions src/Sign.Cli/TrustedSigningCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ internal sealed class TrustedSigningCommand : Command
internal Option<string> CertificateProfileOption { get; } = new(["--trusted-signing-certificate-profile", "-tscp"], TrustedSigningResources.CertificateProfileOptionDescription);
internal AzureCredentialOptions AzureCredentialOptions { get; } = new();

internal Argument<string?> FileArgument { get; } = new("file(s)", Resources.FilesArgumentDescription);
internal Argument<List<string>?> FilesArgument { get; } = new("file(s)", Resources.FilesArgumentDescription) { Arity = ArgumentArity.OneOrMore };

internal TrustedSigningCommand(CodeCommand codeCommand, IServiceProviderFactory serviceProviderFactory)
: base("trusted-signing", TrustedSigningResources.CommandDescription)
Expand All @@ -35,13 +35,13 @@ internal TrustedSigningCommand(CodeCommand codeCommand, IServiceProviderFactory
AddOption(CertificateProfileOption);
AzureCredentialOptions.AddOptionsToCommand(this);

AddArgument(FileArgument);
AddArgument(FilesArgument);

this.SetHandler(async (InvocationContext context) =>
{
string? fileArgument = context.ParseResult.GetValueForArgument(FileArgument);
List<string>? filesArgument = context.ParseResult.GetValueForArgument(FilesArgument);

if (string.IsNullOrEmpty(fileArgument))
if (filesArgument is not { Count: > 0 })
{
context.Console.Error.WriteLine(Resources.MissingFileValue);
context.ExitCode = ExitCode.InvalidOptions;
Expand All @@ -62,7 +62,7 @@ internal TrustedSigningCommand(CodeCommand codeCommand, IServiceProviderFactory

TrustedSigningServiceProvider trustedSigningServiceProvider = new(credential, endpointUrl, accountName, certificateProfileName);

await codeCommand.HandleAsync(context, serviceProviderFactory, trustedSigningServiceProvider, fileArgument);
await codeCommand.HandleAsync(context, serviceProviderFactory, trustedSigningServiceProvider, filesArgument);
});
}
}
Expand Down
2 changes: 1 addition & 1 deletion test/Sign.Cli.Test/SignCommandTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ public void Command_WhenAllOptionsAndArgumentAreValid_HasNoError()
Assert.Equal(KeyVaultUrl, result.GetValueForOption(_azureKeyVaultCommand.UrlOption)!.OriginalString);
Assert.Equal(CertificateName, result.GetValueForOption(_azureKeyVaultCommand.CertificateOption));
Assert.Equal(TimestampUrl, result.GetValueForOption(_codeCommand.TimestampUrlOption)!.OriginalString);
Assert.Equal(File, result.GetValueForArgument(_azureKeyVaultCommand.FileArgument));
Assert.Equal([File], result.GetValueForArgument(_azureKeyVaultCommand.FilesArgument));
}
}
}

0 comments on commit d028616

Please sign in to comment.