opengl source gen tool works
This commit is contained in:
@@ -9,6 +9,7 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using StgSharp.GenerateGL.Generation;
|
||||
using StgSharp.GenerateGL.Registry;
|
||||
|
||||
@@ -23,14 +24,15 @@ namespace StgSharp.GenerateGL
|
||||
private const int QueryErrorExitCode = 1;
|
||||
private const int SuccessExitCode = 0;
|
||||
private const int UsageErrorExitCode = 2;
|
||||
private const string GeneratedFileMarker = "// <auto-generated>";
|
||||
|
||||
public static int Generate(
|
||||
GlRegistryModel registry,
|
||||
GlRegistryProjection projection,
|
||||
IReadOnlyList<string> arguments,
|
||||
out GeneratedFileSet? generatedFiles
|
||||
)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(registry);
|
||||
ArgumentNullException.ThrowIfNull(projection);
|
||||
ArgumentNullException.ThrowIfNull(arguments);
|
||||
generatedFiles = null;
|
||||
|
||||
@@ -40,17 +42,24 @@ namespace StgSharp.GenerateGL
|
||||
return SuccessExitCode;
|
||||
}
|
||||
|
||||
if (arguments.Count != 0)
|
||||
if (arguments.Count > 1)
|
||||
{
|
||||
Console.Error.WriteLine(
|
||||
$"error: unknown generate option '{arguments[0]}'.");
|
||||
Console.Error.WriteLine("error: generate accepts at most one output directory.");
|
||||
Console.Error.WriteLine("Run 'generate --help' for command information.");
|
||||
return UsageErrorExitCode;
|
||||
}
|
||||
|
||||
string? outputDirectory = arguments.Count == 1 ? arguments[0] : null;
|
||||
string? resolvedOutputDirectory = null;
|
||||
try
|
||||
{
|
||||
generatedFiles = OpenGlGenerator.Generate(registry);
|
||||
generatedFiles = OpenGlGenerator.Generate(projection);
|
||||
if (outputDirectory is not null)
|
||||
{
|
||||
resolvedOutputDirectory = WriteGeneratedFiles(
|
||||
generatedFiles,
|
||||
outputDirectory);
|
||||
}
|
||||
}
|
||||
catch (InvalidDataException exception)
|
||||
{
|
||||
@@ -62,14 +71,136 @@ namespace StgSharp.GenerateGL
|
||||
Console.Error.WriteLine($"error: {exception.Message}");
|
||||
return QueryErrorExitCode;
|
||||
}
|
||||
catch (UnauthorizedAccessException exception)
|
||||
{
|
||||
Console.Error.WriteLine($"error: {exception.Message}");
|
||||
return QueryErrorExitCode;
|
||||
}
|
||||
catch (IOException exception)
|
||||
{
|
||||
Console.Error.WriteLine($"error: {exception.Message}");
|
||||
return QueryErrorExitCode;
|
||||
}
|
||||
catch (ArgumentException exception)
|
||||
{
|
||||
Console.Error.WriteLine($"error: {exception.Message}");
|
||||
return QueryErrorExitCode;
|
||||
}
|
||||
catch (NotSupportedException exception)
|
||||
{
|
||||
Console.Error.WriteLine($"error: {exception.Message}");
|
||||
return QueryErrorExitCode;
|
||||
}
|
||||
|
||||
Console.WriteLine(
|
||||
$"Generated {generatedFiles.Files.Count} file(s) in memory.");
|
||||
Console.WriteLine("Use 'list files' and 'preview <filename>' to inspect them.");
|
||||
Console.WriteLine("No files were written to disk.");
|
||||
Console.WriteLine(
|
||||
resolvedOutputDirectory is null
|
||||
? "No files were written to disk."
|
||||
: $"Wrote {generatedFiles.Files.Count} file(s) to " +
|
||||
$"'{resolvedOutputDirectory}'.");
|
||||
return SuccessExitCode;
|
||||
}
|
||||
|
||||
private static string WriteGeneratedFiles(
|
||||
GeneratedFileSet files,
|
||||
string outputDirectory
|
||||
)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(files);
|
||||
ArgumentException.ThrowIfNullOrWhiteSpace(outputDirectory);
|
||||
|
||||
string directory = Path.TrimEndingDirectorySeparator(
|
||||
Path.GetFullPath(outputDirectory));
|
||||
if (!Directory.Exists(directory))
|
||||
{
|
||||
throw new DirectoryNotFoundException(
|
||||
$"Output directory '{directory}' does not exist.");
|
||||
}
|
||||
|
||||
StringComparison pathComparison = OperatingSystem.IsWindows()
|
||||
? StringComparison.OrdinalIgnoreCase
|
||||
: StringComparison.Ordinal;
|
||||
List<StagedGeneratedFile> stagedFiles = new List<StagedGeneratedFile>(
|
||||
files.Files.Count);
|
||||
try
|
||||
{
|
||||
foreach (GeneratedFile file in files.Files)
|
||||
{
|
||||
string fileName = Path.GetFileName(file.Name);
|
||||
if (!string.Equals(fileName, file.Name, StringComparison.Ordinal) ||
|
||||
string.IsNullOrWhiteSpace(fileName))
|
||||
{
|
||||
throw new InvalidDataException(
|
||||
$"Generated file name '{file.Name}' is not a plain file name.");
|
||||
}
|
||||
|
||||
string targetPath = Path.GetFullPath(Path.Combine(directory, fileName));
|
||||
if (!string.Equals(
|
||||
Path.GetDirectoryName(targetPath),
|
||||
directory,
|
||||
pathComparison))
|
||||
{
|
||||
throw new InvalidDataException(
|
||||
$"Generated file '{file.Name}' escapes the output directory.");
|
||||
}
|
||||
|
||||
EnsureTargetCanBeReplaced(targetPath);
|
||||
string temporaryPath = Path.Combine(
|
||||
directory,
|
||||
$".{fileName}.{Guid.NewGuid():N}.tmp");
|
||||
using (FileStream stream = new FileStream(
|
||||
temporaryPath,
|
||||
FileMode.CreateNew,
|
||||
FileAccess.Write,
|
||||
FileShare.None))
|
||||
using (StreamWriter writer = new StreamWriter(
|
||||
stream,
|
||||
new UTF8Encoding(false)))
|
||||
{
|
||||
writer.Write(file.Content);
|
||||
}
|
||||
|
||||
stagedFiles.Add(new StagedGeneratedFile(temporaryPath, targetPath));
|
||||
}
|
||||
|
||||
foreach (StagedGeneratedFile file in stagedFiles)
|
||||
{
|
||||
File.Move(file.TemporaryPath, file.TargetPath, true);
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
foreach (StagedGeneratedFile file in stagedFiles)
|
||||
{
|
||||
if (File.Exists(file.TemporaryPath))
|
||||
{
|
||||
File.Delete(file.TemporaryPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return directory;
|
||||
}
|
||||
|
||||
private static void EnsureTargetCanBeReplaced(
|
||||
string targetPath
|
||||
)
|
||||
{
|
||||
if (!File.Exists(targetPath))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
string? firstLine = File.ReadLines(targetPath).FirstOrDefault();
|
||||
if (!string.Equals(firstLine, GeneratedFileMarker, StringComparison.Ordinal))
|
||||
{
|
||||
throw new IOException(
|
||||
$"Refusing to overwrite non-generated file '{targetPath}'.");
|
||||
}
|
||||
}
|
||||
|
||||
public static int ListFiles(
|
||||
GeneratedFileSet files,
|
||||
IReadOnlyList<string> arguments
|
||||
@@ -90,7 +221,7 @@ namespace StgSharp.GenerateGL
|
||||
return QueryErrorExitCode;
|
||||
}
|
||||
|
||||
Console.WriteLine("Generated files (memory only)");
|
||||
Console.WriteLine("Generated files held in the current session");
|
||||
for (int index = 0; index < files.Files.Count; index++)
|
||||
{
|
||||
GeneratedFile file = files.Files[index];
|
||||
@@ -141,16 +272,23 @@ namespace StgSharp.GenerateGL
|
||||
Console.WriteLine();
|
||||
Console.WriteLine("Usage:");
|
||||
Console.WriteLine(" generate");
|
||||
Console.WriteLine(" generate <output-directory>");
|
||||
Console.WriteLine(" generate --help");
|
||||
Console.WriteLine();
|
||||
Console.WriteLine("Status:");
|
||||
Console.WriteLine(" Output is retained in the current process only.");
|
||||
Console.WriteLine(" Running 'generate' does not create or modify disk files.");
|
||||
Console.WriteLine("Output:");
|
||||
Console.WriteLine(" Without a directory, output is retained in memory only.");
|
||||
Console.WriteLine(" The output directory must already exist and be writable.");
|
||||
Console.WriteLine(" Existing files are replaced only when marked as generated.");
|
||||
Console.WriteLine();
|
||||
Console.WriteLine("Inspection:");
|
||||
Console.WriteLine(" list files");
|
||||
Console.WriteLine(" preview <filename>");
|
||||
}
|
||||
|
||||
private sealed record StagedGeneratedFile(
|
||||
string TemporaryPath,
|
||||
string TargetPath
|
||||
);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user