From e639f10b46a9a88244ebee56383904f1d5422bb0 Mon Sep 17 00:00:00 2001 From: Ikiru Yoshizaki <3856350+guitarrapc@users.noreply.github.com> Date: Tue, 17 Dec 2024 15:42:57 +0900 Subject: [PATCH] feat: add ValidateArtifactCommand --- src/Actions.Tests/FileExistsCommandTest.cs | 100 ++++++++++++++++++ ...Command.cs => UpdateVersionCommandTest.cs} | 6 +- src/Actions/Commands/CreateDummyCommand.cs | 24 ++++- src/Actions/Commands/FileExsistsCommand.cs | 95 +++++++++++++++++ src/Actions/Program.cs | 17 ++- src/Actions/Properties/launchSettings.json | 17 +++ 6 files changed, 253 insertions(+), 6 deletions(-) create mode 100644 src/Actions.Tests/FileExistsCommandTest.cs rename src/Actions.Tests/{UpdateVersionCommand.cs => UpdateVersionCommandTest.cs} (91%) create mode 100644 src/Actions/Commands/FileExsistsCommand.cs diff --git a/src/Actions.Tests/FileExistsCommandTest.cs b/src/Actions.Tests/FileExistsCommandTest.cs new file mode 100644 index 0000000..4616495 --- /dev/null +++ b/src/Actions.Tests/FileExistsCommandTest.cs @@ -0,0 +1,100 @@ +using Actions.Commands; + +namespace Actions.Tests; + +public class FileExistsCommandTest +{ + [Fact] + public void EmptyPathTest() + { + var command = new FileExsistsCommand(""); + Assert.Throws(() => command.Validate()); + } + + [Fact] + public void FullPathTest() + { + var path = $".tests/{nameof(FileExistsCommandTest)}/{nameof(FullPathTest)}/dummy.nupkg"; + var dir = Path.GetDirectoryName(path)!; + if (!Directory.Exists(dir)) Directory.CreateDirectory(dir); + File.WriteAllText(path, ""); + + var command = new FileExsistsCommand(path); + command.Validate(); + } + + [Fact] + public void WildcardFileTest() + { + var dir = $".tests/{nameof(FileExistsCommandTest)}/{nameof(WildcardFileTest)}"; + var items = new[] { "foo", "bar", "piyo" }; + foreach (var item in items) { + if (!Directory.Exists(dir)) Directory.CreateDirectory(dir); + File.WriteAllText(Path.Combine(dir, item), ""); + } + + var command = new FileExsistsCommand($"{dir}/*"); + command.Validate(); + + var command2 = new FileExsistsCommand($"{dir}/foo"); + command2.Validate(); + } + + [Fact] + public void WildcardDirectoryTest() + { + var dir = $".tests/{nameof(FileExistsCommandTest)}/{nameof(WildcardDirectoryTest)}"; + var items = new[] { "foo", "bar", "piyo" }; + foreach (var item in items) + { + if (!Directory.Exists(dir)) Directory.CreateDirectory(dir); + File.WriteAllText(Path.Combine(dir, item), ""); + } + + var command = new FileExsistsCommand($".tests/{nameof(FileExistsCommandTest)}/*/foo"); + command.Validate(); + + var command2 = new FileExsistsCommand($".tests/{nameof(FileExistsCommandTest)}/{nameof(WildcardDirectoryTest)}/foo"); + command2.Validate(); + + var failCommand = new FileExsistsCommand($".tests/{nameof(FileExistsCommandTest)}/{nameof(WildcardDirectoryTest)}/*/foo"); + Assert.Throws(() => failCommand.Validate()); + } + + [Fact] + public void RecursiveWildcardDirectoryTest() + { + var dir = $".tests/{nameof(FileExistsCommandTest)}/{nameof(RecursiveWildcardDirectoryTest)}"; + var items = new[] { "foo", "bar", "piyo" }; + foreach (var item in items) + { + if (!Directory.Exists(dir)) Directory.CreateDirectory(dir); + File.WriteAllText(Path.Combine(dir, item), ""); + } + + var command = new FileExsistsCommand($".tests/{nameof(FileExistsCommandTest)}/**/foo"); + command.Validate(); + + var command2 = new FileExsistsCommand($".tests/{nameof(FileExistsCommandTest)}/{nameof(WildcardDirectoryTest)}/**/foo"); + command2.Validate(); + } + + [Fact] + public void RecursiveWildcardDirectoryAndFileTest() + { + var dirBase = $".tests/{nameof(FileExistsCommandTest)}/{nameof(RecursiveWildcardDirectoryAndFileTest)}"; + var items = new[] { "foo", "bar", "piyo" }; + foreach (var item in items) + { + var dir = Path.Combine(dirBase, item); + if (!Directory.Exists(dir)) Directory.CreateDirectory(dir); + File.WriteAllText(Path.Combine(dir, item), ""); + } + + var command = new FileExsistsCommand($"{dirBase}/**/*"); + command.Validate(); + + var command2 = new FileExsistsCommand($"{dirBase}/foo/foo"); + command2.Validate(); + } +} \ No newline at end of file diff --git a/src/Actions.Tests/UpdateVersionCommand.cs b/src/Actions.Tests/UpdateVersionCommandTest.cs similarity index 91% rename from src/Actions.Tests/UpdateVersionCommand.cs rename to src/Actions.Tests/UpdateVersionCommandTest.cs index 96a95b7..3b53e10 100644 --- a/src/Actions.Tests/UpdateVersionCommand.cs +++ b/src/Actions.Tests/UpdateVersionCommandTest.cs @@ -9,7 +9,7 @@ public class UpdateVersionCommandTest public void UnityUpmTest() { var version = "1.0.0"; - var path = $"{nameof(UpdateVersionCommandTest)}/package.json"; + var path = $".tests/{nameof(UpdateVersionCommandTest)}{nameof(UnityUpmTest)}/package.json"; var contents = """ { "name": "com.unity.plugin.example", @@ -70,7 +70,7 @@ public void UnityUpmTest() public void GodotPluginTest() { var version = "1.0.0"; - var path = $"{nameof(GodotPluginTest)}/plugin.cfg"; + var path = $".tests/{nameof(UpdateVersionCommandTest)}/{nameof(GodotPluginTest)}/plugin.cfg"; var contents = """ [plugin] @@ -105,7 +105,7 @@ public void GodotPluginTest() public void DirectoryBuildPropsTest() { var version = "1.0.0"; - var path = $"{nameof(DirectoryBuildPropsTest)}/Directory.Build.props"; + var path = $".tests/{nameof(UpdateVersionCommandTest)}/{nameof(DirectoryBuildPropsTest)}/Directory.Build.props"; var contents = """ diff --git a/src/Actions/Commands/CreateDummyCommand.cs b/src/Actions/Commands/CreateDummyCommand.cs index 06431ef..dde7581 100644 --- a/src/Actions/Commands/CreateDummyCommand.cs +++ b/src/Actions/Commands/CreateDummyCommand.cs @@ -2,7 +2,13 @@ public class CreateDummyCommand { - public void CreateDummyFiles(string basePath) + public void CreateDummy(string basePath) + { + DummyVersionFiles(basePath); + DummyAssetFiles(Path.Combine(basePath, "downloads/")); + } + + private void DummyVersionFiles(string basePath) { var upm = ("package.json", """ { @@ -44,6 +50,7 @@ public void CreateDummyFiles(string basePath) """); + Console.WriteLine($"{nameof(DummyVersionFiles)}"); foreach (var (file, contents) in new[] { upm, godot, directoryBuildProps }) { var path = Path.Combine(basePath, file); @@ -54,4 +61,19 @@ public void CreateDummyFiles(string basePath) File.WriteAllText(path, contents); } } + + private void DummyAssetFiles(string basePath) + { + Console.WriteLine($"{nameof(DummyAssetFiles)}"); + var items = new[] { "foo", "bar", "piyo" }; + foreach (var item in items) + { + var path = Path.Combine(basePath, item); + if (!Directory.Exists(basePath)) + Directory.CreateDirectory(basePath); + + Console.WriteLine($"- {path} ..."); + File.WriteAllText(path, ""); + } + } } diff --git a/src/Actions/Commands/FileExsistsCommand.cs b/src/Actions/Commands/FileExsistsCommand.cs new file mode 100644 index 0000000..b55441e --- /dev/null +++ b/src/Actions/Commands/FileExsistsCommand.cs @@ -0,0 +1,95 @@ +namespace Actions.Commands; + +public class FileExsistsCommand(string pathPattern) +{ + public void Validate() + { + // do nothing for empty input + if (string.IsNullOrWhiteSpace(pathPattern)) + { + throw new ActionCommandException("Input path was empty."); + } + + // Handle glob path pattern. + // /foo/bar/**/* + // /foo/bar/*.txt + if (ContainsGlobPattern(pathPattern)) + { + if (!FileExistsWithGlob(pathPattern)) + { + throw new ActionCommandException(pathPattern, new FileNotFoundException(pathPattern)); + } + return; + } + + // Specified full path pattern... + // /foo/bar/piyo/poyo.txt + if (!File.Exists(pathPattern)) + { + throw new ActionCommandException(pathPattern, new FileNotFoundException(pathPattern)); + } + } + + private static bool ContainsGlobPattern(string pattern) => pattern.Contains('*') || pattern.Contains('?'); + private static bool FileExistsWithGlob(string pattern) + { + try + { + pattern = pattern.Replace("\\", "/"); + string directory = GetParentDirectoryPath(pattern) ?? Directory.GetCurrentDirectory(); + string searchPattern = Path.GetFileName(pattern); + + if (pattern.Contains("/**/")) + { + return Directory.EnumerateFiles(directory, searchPattern, SearchOption.AllDirectories).Any(); + } + if (pattern.Contains("*/")) + { + return EnumerateFileWildcard(pattern, searchPattern, SearchOption.AllDirectories).Any(); + } + else + { + return Directory.EnumerateFiles(directory, searchPattern, SearchOption.TopDirectoryOnly).Any(); + } + } + catch (Exception ex) + { + throw new ActionCommandException($"Error happen on checking file. Is specified path correct? path: {pattern}", ex); + } + } + + private static string GetParentDirectoryPath(string path) + { + var limit = 5; + var current = 0; + var dir = path; + var fileName = Path.GetFileName(dir); + var next = false; + do + { + dir = Path.GetDirectoryName(dir) ?? ""; + fileName = Path.GetFileName(dir); + current++; + if (current >= limit) + { + throw new ActionCommandException($"Recursively approaced parent directory but reached limit. {current}/{limit}"); + } + next = fileName == "**" || fileName == "*"; + } while (next); + + return dir; + } + + private static IEnumerable EnumerateFileWildcard(string path, string searchPattern, SearchOption searchOption) + { + var fileName = Path.GetFileName(path); + if (fileName == "*") + { + return Directory.GetDirectories(Path.GetDirectoryName(path)!).SelectMany(x => Directory.GetFiles(x, searchPattern, searchOption)); + } + else + { + return EnumerateFileWildcard(Path.GetDirectoryName(path)!, searchPattern, searchOption); + } + } +} diff --git a/src/Actions/Program.cs b/src/Actions/Program.cs index 18288b0..2cf68a0 100644 --- a/src/Actions/Program.cs +++ b/src/Actions/Program.cs @@ -58,6 +58,19 @@ public void UpdateVersion(string version, string path, bool dryRun) Console.WriteLine($"Completed ..."); } + /// + /// Validate specified path contains file + /// + /// + [Command("validate-file-exists")] + public void ValidateFileExists(string pathPattern) + { + Console.WriteLine($"Validating path, {pathPattern}"); + var command = new FileExsistsCommand(pathPattern); + command.Validate(); + Console.WriteLine($"Completed ..."); + } + /// /// Create dummy files /// @@ -68,7 +81,7 @@ public void CreateDummy(string basePath) Console.WriteLine($"Creating dummy files, under {basePath} ..."); var command = new CreateDummyCommand(); - command.CreateDummyFiles(basePath); + command.CreateDummy(basePath); Console.WriteLine($"Completed ..."); } @@ -83,7 +96,7 @@ public void CreateDummy(string basePath) }; } - public class ActionCommandException(string message) : Exception(message) + public class ActionCommandException(string message, Exception? innterException = null) : Exception(message, innterException) { } } \ No newline at end of file diff --git a/src/Actions/Properties/launchSettings.json b/src/Actions/Properties/launchSettings.json index 85ef9d6..8c71e71 100644 --- a/src/Actions/Properties/launchSettings.json +++ b/src/Actions/Properties/launchSettings.json @@ -46,6 +46,23 @@ "commandName": "Project", "commandLineArgs": "update-version --version 1.0.0 --path ./dummy/Directory.Build.props" }, + // validate-file-exsits + "validate-file-exsits (path: foo)": { + "commandName": "Project", + "commandLineArgs": "validate-file-exists --path-pattern ./dummy/downloads/foo" + }, + "validate-file-exsits (path: *)": { + "commandName": "Project", + "commandLineArgs": "validate-file-exists --path-pattern ./dummy/downloads/*" + }, + "validate-file-exsits (path: */foo)": { + "commandName": "Project", + "commandLineArgs": "validate-file-exists --path-pattern ./dummy/*/foo" + }, + "validate-file-exsits (path: **/foo)": { + "commandName": "Project", + "commandLineArgs": "validate-file-exists --path-pattern ./dummy/**/foo" + }, // create-dummy "create-dummy (help)": { "commandName": "Project",