Skip to content

Commit 2b6c793

Browse files
authored
Merge pull request #385 from wojtpl2/validate_array_of_FileInfo
Support attribute of array of FileInfo or DirectoryInfo
2 parents edecb0b + 2c93189 commit 2b6c793

File tree

2 files changed

+147
-0
lines changed

2 files changed

+147
-0
lines changed

src/System.CommandLine.Tests/ParsingValidationTests.cs

+127
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
using System.CommandLine.Invocation;
66
using System.IO;
77
using System.Linq;
8+
using System.Reflection;
89
using FluentAssertions;
910
using Xunit;
1011
using Xunit.Abstractions;
@@ -192,6 +193,66 @@ public void An_argument_can_be_invalid_based_on_file_existence()
192193
e.Message == $"File does not exist: {guid}");
193194
}
194195

196+
[Fact]
197+
public void An_argument_with_multiple_file_info_can_be_invalid_based_on_first_file_existence()
198+
{
199+
var command = new Command(
200+
"move",
201+
argument: new Argument<FileInfo[]>
202+
{
203+
Arity = ArgumentArity.ZeroOrMore
204+
}.ExistingOnly());
205+
command.AddOption(
206+
new Option(
207+
"--to",
208+
argument: new Argument
209+
{
210+
Arity = ArgumentArity.ExactlyOne
211+
}));
212+
213+
Guid guid1 = Guid.NewGuid();
214+
Guid guid2 = Guid.NewGuid();
215+
var result =
216+
command.Parse(
217+
$@"move ""{guid1}"" ""{guid2}"" --to ""{Path.Combine(Directory.GetCurrentDirectory(), ".trash")}""");
218+
219+
result.Errors
220+
.Should()
221+
.HaveCount(1)
222+
.And
223+
.Contain(e => e.SymbolResult.Name == "move" && e.Message == $"File does not exist: {guid1}");
224+
}
225+
226+
[Fact]
227+
public void An_argument_with_multiple_file_info_can_be_invalid_based_on_second_file_existence()
228+
{
229+
var command = new Command(
230+
"move",
231+
argument: new Argument<FileInfo[]>
232+
{
233+
Arity = ArgumentArity.ZeroOrMore
234+
}.ExistingOnly());
235+
command.AddOption(
236+
new Option(
237+
"--to",
238+
argument: new Argument
239+
{
240+
Arity = ArgumentArity.ExactlyOne
241+
}));
242+
243+
var executingAssemblyLocation = Assembly.GetExecutingAssembly().Location;
244+
var guid = Guid.NewGuid();
245+
var result =
246+
command.Parse(
247+
$@"move ""{executingAssemblyLocation}"" ""{guid}"" --to ""{Path.Combine(Directory.GetCurrentDirectory(), ".trash")}""");
248+
249+
result.Errors
250+
.Should()
251+
.HaveCount(1)
252+
.And
253+
.Contain(e => e.SymbolResult.Name == "move" && e.Message == $"File does not exist: {guid}");
254+
}
255+
195256
[Fact]
196257
public void An_argument_can_be_invalid_based_on_directory_existence()
197258
{
@@ -223,6 +284,72 @@ public void An_argument_can_be_invalid_based_on_directory_existence()
223284
e.Message == $"Directory does not exist: {trash}");
224285
}
225286

287+
[Fact]
288+
public void An_argument_with_multiple_directory_info_can_be_invalid_based_on_first_directory_existence()
289+
{
290+
var command = new Command(
291+
"move",
292+
argument: new Argument
293+
{
294+
Arity = ArgumentArity.ExactlyOne
295+
});
296+
command.AddOption(
297+
new Option("--to",
298+
argument: new Argument<DirectoryInfo[]>
299+
{
300+
Arity = ArgumentArity.ZeroOrMore
301+
}.ExistingOnly()));
302+
303+
var currentDirectory = Directory.GetCurrentDirectory();
304+
var trash1 = Path.Combine(currentDirectory, ".trash1");
305+
var trash2 = Path.Combine(currentDirectory, ".trash2");
306+
307+
var commandLine = $@"move ""{currentDirectory}"" --to ""{trash1}"" ""{trash2}""";
308+
309+
var result = command.Parse(commandLine);
310+
311+
_output.WriteLine(result.Diagram());
312+
313+
result.Errors
314+
.Should()
315+
.HaveCount(1)
316+
.And
317+
.Contain(e => e.SymbolResult.Name == "to" && e.Message == $"Directory does not exist: {trash1}");
318+
}
319+
320+
[Fact]
321+
public void An_argument_with_multiple_directory_info_can_be_invalid_based_on_second_directory_existence()
322+
{
323+
var command = new Command(
324+
"move",
325+
argument: new Argument
326+
{
327+
Arity = ArgumentArity.ExactlyOne
328+
});
329+
command.AddOption(
330+
new Option("--to",
331+
argument: new Argument<DirectoryInfo[]>
332+
{
333+
Arity = ArgumentArity.ZeroOrMore
334+
}.ExistingOnly()));
335+
336+
var currentDirectory = Directory.GetCurrentDirectory();
337+
var executionAssemblyPath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
338+
var trash = Path.Combine(currentDirectory, ".trash2");
339+
340+
var commandLine = $@"move ""{currentDirectory}"" --to ""{executionAssemblyPath}"" ""{trash}""";
341+
342+
var result = command.Parse(commandLine);
343+
344+
_output.WriteLine(result.Diagram());
345+
346+
result.Errors
347+
.Should()
348+
.HaveCount(1)
349+
.And
350+
.Contain(e => e.SymbolResult.Name == "to" && e.Message == $"Directory does not exist: {trash}");
351+
}
352+
226353
[Fact]
227354
public void A_command_with_subcommands_is_invalid_to_invoke_if_it_has_no_handler()
228355
{

src/System.CommandLine/Builder/ArgumentExtensions.cs

+20
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,26 @@ public static Argument<DirectoryInfo> ExistingOnly(this Argument<DirectoryInfo>
5959
return argument;
6060
}
6161

62+
public static Argument<FileInfo[]> ExistingOnly(this Argument<FileInfo[]> argument)
63+
{
64+
argument.AddValidator(symbol =>
65+
symbol.Arguments
66+
.Where(filePath => !File.Exists(filePath))
67+
.Select(symbol.ValidationMessages.FileDoesNotExist)
68+
.FirstOrDefault());
69+
return argument;
70+
}
71+
72+
public static Argument<DirectoryInfo[]> ExistingOnly(this Argument<DirectoryInfo[]> argument)
73+
{
74+
argument.AddValidator(symbol =>
75+
symbol.Arguments
76+
.Where(filePath => !Directory.Exists(filePath))
77+
.Select(symbol.ValidationMessages.DirectoryDoesNotExist)
78+
.FirstOrDefault());
79+
return argument;
80+
}
81+
6282
public static TArgument LegalFilePathsOnly<TArgument>(
6383
this TArgument argument)
6484
where TArgument : Argument

0 commit comments

Comments
 (0)