From cd0c4420e1cfd99a1f5920e6340a8c8610959b30 Mon Sep 17 00:00:00 2001 From: Zev Spitz Date: Sun, 16 Jan 2022 03:27:32 +0200 Subject: [PATCH] Utils: generate solution and project files --- .../DotnetUtils/DotnetUtils/Extensions.cs | 8 +-- .../DotnetUtils/DotnetUtils/Methods.cs | 56 +++++++++++++++++++ .../DotnetUtils/DotnetUtils/PortInfo.cs | 19 +++++-- .../DotnetUtils/DotnetUtils/Program.cs | 55 +++++++++++++++++- 4 files changed, 125 insertions(+), 13 deletions(-) create mode 100644 00_Utilities/DotnetUtils/DotnetUtils/Methods.cs diff --git a/00_Utilities/DotnetUtils/DotnetUtils/Extensions.cs b/00_Utilities/DotnetUtils/DotnetUtils/Extensions.cs index 82ff9532..a0f52bee 100644 --- a/00_Utilities/DotnetUtils/DotnetUtils/Extensions.cs +++ b/00_Utilities/DotnetUtils/DotnetUtils/Extensions.cs @@ -1,4 +1,5 @@ using System.Diagnostics.CodeAnalysis; +using static System.IO.Path; namespace DotnetUtils; @@ -18,10 +19,7 @@ public static class Extensions { rootPath.IsNullOrWhitespace() ) { return path; } - var path1 = path.TrimEnd('\\'); - rootPath = rootPath.TrimEnd('\\'); - if (!path1.StartsWith(rootPath, StringComparison.InvariantCultureIgnoreCase)) { return path; } - - return path1[(rootPath.Length + 1)..]; // ignore the initial / + path = path.TrimEnd('\\'); // remove trailing backslash, if present + return GetRelativePath(rootPath, path.TrimEnd('\\')); } } diff --git a/00_Utilities/DotnetUtils/DotnetUtils/Methods.cs b/00_Utilities/DotnetUtils/DotnetUtils/Methods.cs new file mode 100644 index 00000000..de69131f --- /dev/null +++ b/00_Utilities/DotnetUtils/DotnetUtils/Methods.cs @@ -0,0 +1,56 @@ +using System.Diagnostics; + +namespace DotnetUtils; + +public static class Methods { + public static ProcessResult RunProcess(string filename, string arguments) { + var process = new Process() { + StartInfo = { + FileName = filename, + Arguments = arguments, + UseShellExecute = false, + CreateNoWindow = true, + RedirectStandardOutput = true, + RedirectStandardError = true, + }, + EnableRaisingEvents = true + }; + return RunProcess(process); + } + + public static ProcessResult RunProcess(Process process, string input = "") { + var (output, error) = ("", ""); + var (redirectOut, redirectErr) = ( + process.StartInfo.RedirectStandardOutput, + process.StartInfo.RedirectStandardError + ); + if (redirectOut) { + process.OutputDataReceived += (s, ea) => output += ea.Data + "\n"; + } + if (redirectErr) { + process.ErrorDataReceived += (s, ea) => error += ea.Data + "\n"; + } + + if (!process.Start()) { + throw new InvalidOperationException(); + }; + + if (redirectOut) { process.BeginOutputReadLine(); } + if (redirectErr) { process.BeginErrorReadLine(); } + if (!string.IsNullOrEmpty(input)) { + process.StandardInput.WriteLine(input); + process.StandardInput.Close(); + } + process.WaitForExit(); + return new ProcessResult(process.ExitCode, output, error); + } +} + +public sealed record ProcessResult(int ExitCode, string StdOut, string StdErr) { + public override string? ToString() => + StdOut + + (StdOut is not (null or "") && ExitCode > 0 ? "\n" : "") + + (ExitCode > 0 ? + $"{ExitCode}\n{StdErr}" : + ""); +} diff --git a/00_Utilities/DotnetUtils/DotnetUtils/PortInfo.cs b/00_Utilities/DotnetUtils/DotnetUtils/PortInfo.cs index 894c8834..547e2878 100644 --- a/00_Utilities/DotnetUtils/DotnetUtils/PortInfo.cs +++ b/00_Utilities/DotnetUtils/DotnetUtils/PortInfo.cs @@ -1,5 +1,4 @@ -using System.Reflection; -using static System.IO.Directory; +using static System.IO.Directory; using static System.IO.Path; using static DotnetUtils.Globals; @@ -17,6 +16,14 @@ public record PortInfo( MatchCasing = MatchCasing.CaseInsensitive }; + // .NET namespaces cannot have a digit as the first character + // For games whose name starts with a digit, we map the name to a specific string + private static readonly Dictionary specialGameNames = new() { + { "3-D_Plot", "ThreeDPlot" }, + { "3-D_Tic-Tac-Toe", "ThreeDTicTacToe" }, + { "23_Matches", "TwentyThreeMatches"} + }; + public static PortInfo? Create(string fullPath, string langKeyword) { var folderName = GetFileName(fullPath); var parts = folderName.Split('_', 2); @@ -27,9 +34,11 @@ public record PortInfo( (int?)null; var gameName = - parts.Length > 1 ? - parts[1].Replace("_", "") : - null; + parts.Length == 0 ? + null : + specialGameNames.TryGetValue(parts[1], out var specialName) ? + specialName : + parts[1].Replace("_", "").Replace("-", ""); if (index is 0 or null || gameName is null) { return null; } diff --git a/00_Utilities/DotnetUtils/DotnetUtils/Program.cs b/00_Utilities/DotnetUtils/DotnetUtils/Program.cs index 6d4594b7..f082060c 100644 --- a/00_Utilities/DotnetUtils/DotnetUtils/Program.cs +++ b/00_Utilities/DotnetUtils/DotnetUtils/Program.cs @@ -1,6 +1,8 @@ -using DotnetUtils; +using System.Diagnostics; +using DotnetUtils; using static System.Console; using static System.IO.Path; +using static DotnetUtils.Methods; var infos = PortInfos.Get; @@ -11,7 +13,10 @@ var actions = new (Action action, string description)[] { (multipleSlns, "Output multiple sln files"), (missingProj, "Output missing project file"), (unexpectedProjName, "Output misnamed project files"), - (multipleProjs, "Output multiple project files") + (multipleProjs, "Output multiple project files"), + + (generateMissingSlns, "Generate solution files when missing"), + (generateMissingProjs, "Generate project files when missing") }; foreach (var (_, description, index) in actions.WithIndex()) { @@ -159,8 +164,52 @@ void multipleProjs() { WriteLine(item.LangPath); WriteLine(); printProjs(item); - } WriteLine(); WriteLine($"Count: {data.Length}"); } + +void generateMissingSlns() { + foreach (var item in infos.Where(x => !x.Slns.Any())) { + var result = RunProcess("dotnet", $"new sln -n {item.GameName} -o {item.LangPath}"); + WriteLine(result); + + var slnFullPath = Combine(item.LangPath, $"{item.GameName}.sln"); + foreach (var proj in item.Projs) { + result = RunProcess("dotnet", $"sln {slnFullPath} add {proj}"); + WriteLine(result); + } + } +} + +void generateMissingProjs() { + foreach (var item in infos.Where(x => !x.Projs.Any())) { + var (langArg, langVersion) = item.Lang switch { + "csharp" => ("\"C#\"", 10), + "vbnet" => ("\"VB\"", 16.9), + _ => throw new InvalidOperationException() + }; + + var result = RunProcess("dotnet", $"new console --language {langArg} --name {item.GameName}.{item.ProjExt} -o {item.LangPath} -f net6.0 --langversion {langVersion}"); + WriteLine(result); + + var projFullPath = Combine(item.LangPath, $"{item.GameName}.{item.ProjExt}"); + if (item.Slns.Length == 1) { + result = RunProcess("dotnet", $"sln {item.Slns[0]} add {projFullPath}"); + WriteLine(result); + } + } +} + +void checkProjects() { + // warn if project files do not: + // target .NET 6 + // implicit using + // nullable enable + // warn if none og the projects have: + // output type exe +} + +void tryBuild() { + // if has code files, try to build +}