diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index c0fe5f2..959be95 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -7,7 +7,7 @@ "workspaceFolder": "/workspaces/${localWorkspaceFolderBasename}", "features": { "ghcr.io/devcontainers/features/dotnet:2": { - "version": "latest" + "version": "6.0" }, "ghcr.io/devcontainers/features/github-cli:1": { "installDirectlyFromGitHubRelease": true, diff --git a/Makefile b/Makefile deleted file mode 100644 index 42dc80a..0000000 --- a/Makefile +++ /dev/null @@ -1,19 +0,0 @@ -.PHONY: build -build: - dotnet build --configuration Release - -.PHONY: pack -pack: build - dotnet pack --configuration Release - -.PHONY: clean -clean: - dotnet clean - rm -rf ./artifacts - rm -rf ./src/**/bin - rm -rf ./src/**/obj - -.PHONY: sdks -sdks: - sudo ./scripts/dotnet-install.sh --channel 8.0 --install-dir ${DOTNET_ROOT} - sudo ./scripts/dotnet-install.sh --channel 6.0 --install-dir ${DOTNET_ROOT} diff --git a/src/Atlas.Provider.Loader/Exe.cs b/src/Atlas.Provider.Loader/Exe.cs new file mode 100644 index 0000000..fde015f --- /dev/null +++ b/src/Atlas.Provider.Loader/Exe.cs @@ -0,0 +1,144 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Diagnostics; +using System.Text; + +namespace Atlas.Provider.Loader; + +// Copied from https://github.com/dotnet/efcore/blob/6df2608e585f85c7bce1b0a4832c4b519cf592ad/src/dotnet-ef/Exe.cs +internal static class Exe +{ + public static int Run( + string executable, + IReadOnlyList args, + string? workingDirectory = null, + Action? handleOutput = null, + Action? handleError = null, + Action? processCommandLine = null) + { + var arguments = ToArguments(args); + + processCommandLine?.Invoke(executable + " " + arguments); + + var startInfo = new ProcessStartInfo + { + FileName = executable, + Arguments = arguments, + UseShellExecute = false, + RedirectStandardOutput = handleOutput != null, + RedirectStandardError = handleError != null + }; + if (workingDirectory != null) + { + startInfo.WorkingDirectory = workingDirectory; + } + + var process = new Process + { + StartInfo = startInfo + }; + + if (handleOutput != null) + { + process.OutputDataReceived += (sender, args) => handleOutput(args.Data); + } + + if (handleError != null) + { + process.ErrorDataReceived += (sender, args) => handleError(args.Data); + } + + process.Start(); + + if (handleOutput != null) + { + process.BeginOutputReadLine(); + } + + if (handleError != null) + { + process.BeginErrorReadLine(); + } + + process.WaitForExit(); + + return process.ExitCode; + } + + public static string ToArguments(IReadOnlyList args) + { + var builder = new StringBuilder(); + for (var i = 0; i < args.Count; i++) + { + if (i != 0) + { + builder.Append(' '); + } + + if (args[i].Length == 0) + { + builder.Append("\"\""); + + continue; + } + + if (args[i].IndexOf(' ') == -1) + { + builder.Append(args[i]); + + continue; + } + + builder.Append('"'); + + var pendingBackslashes = 0; + for (var j = 0; j < args[i].Length; j++) + { + switch (args[i][j]) + { + case '\"': + if (pendingBackslashes != 0) + { + builder.Append('\\', pendingBackslashes * 2); + pendingBackslashes = 0; + } + + builder.Append("\\\""); + break; + + case '\\': + pendingBackslashes++; + break; + + default: + if (pendingBackslashes != 0) + { + if (pendingBackslashes == 1) + { + builder.Append('\\'); + } + else + { + builder.Append('\\', pendingBackslashes * 2); + } + + pendingBackslashes = 0; + } + + builder.Append(args[i][j]); + break; + } + } + + if (pendingBackslashes != 0) + { + builder.Append('\\', pendingBackslashes * 2); + } + + builder.Append('"'); + } + + return builder.ToString(); + } +} \ No newline at end of file diff --git a/src/Atlas.Provider.Loader/Executor/Exe.cs b/src/Atlas.Provider.Loader/Executor/Exe.cs deleted file mode 100644 index 5acfa23..0000000 --- a/src/Atlas.Provider.Loader/Executor/Exe.cs +++ /dev/null @@ -1,119 +0,0 @@ -/* -Title: Exe -Type: Source Code -Availability: https://github.com/dotnet/efcore/blob/9262a34db65ce52085ded548fc480522051cec2b/src/dotnet-ef/Exe.cs -*/ - -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -using System.Diagnostics; -using System.Text; - -namespace Atlas.Provider.Loader.Executor; - -internal static class Exe -{ - public static int Run( - string executable, - IReadOnlyList args, - string? workingDirectory = null, - bool interceptOutput = false) - { - var arguments = ToArguments(args); - - var startInfo = new ProcessStartInfo - { - FileName = executable, - Arguments = arguments, - UseShellExecute = false, - RedirectStandardOutput = interceptOutput - }; - if (workingDirectory != null) - { - startInfo.WorkingDirectory = workingDirectory; - } - - var process = Process.Start(startInfo)!; - - process.WaitForExit(); - - return process.ExitCode; - } - - private static string ToArguments(IReadOnlyList args) - { - var builder = new StringBuilder(); - for (var i = 0; i < args.Count; i++) - { - if (i != 0) - { - builder.Append(' '); - } - - if (args[i].Length == 0) - { - builder.Append("\"\""); - - continue; - } - - if (args[i].IndexOf(' ') == -1) - { - builder.Append(args[i]); - - continue; - } - - builder.Append('"'); - - var pendingBackslashes = 0; - for (var j = 0; j < args[i].Length; j++) - { - switch (args[i][j]) - { - case '\"': - if (pendingBackslashes != 0) - { - builder.Append('\\', pendingBackslashes * 2); - pendingBackslashes = 0; - } - - builder.Append("\\\""); - break; - - case '\\': - pendingBackslashes++; - break; - - default: - if (pendingBackslashes != 0) - { - if (pendingBackslashes == 1) - { - builder.Append('\\'); - } - else - { - builder.Append('\\', pendingBackslashes * 2); - } - - pendingBackslashes = 0; - } - - builder.Append(args[i][j]); - break; - } - } - - if (pendingBackslashes != 0) - { - builder.Append('\\', pendingBackslashes * 2); - } - - builder.Append('"'); - } - - return builder.ToString(); - } -} diff --git a/src/Atlas.Provider.Loader/Program.cs b/src/Atlas.Provider.Loader/Program.cs index 2c8d610..ec0fc73 100644 --- a/src/Atlas.Provider.Loader/Program.cs +++ b/src/Atlas.Provider.Loader/Program.cs @@ -90,7 +90,7 @@ static void Main( arguments.Add("--nullable"); } // dotnet exec [runtime-options] [path-to-application] [arguments] - Executor.Exe.Run("dotnet", [ + Exe.Run("dotnet", [ "exec", .. runtimeOpts, Path.Combine(loaderDirPath!, AssemblyName + ".dll"), diff --git a/src/Atlas.Provider.Loader/Project.cs b/src/Atlas.Provider.Loader/Project.cs index e1d7226..4fc19e3 100644 --- a/src/Atlas.Provider.Loader/Project.cs +++ b/src/Atlas.Provider.Loader/Project.cs @@ -71,7 +71,7 @@ public static Project FromFile( { propertyArg += ";RuntimeIdentifier=" + runtime; } - var exitCode = Executor.Exe.Run("dotnet", [ + var exitCode = Exe.Run("dotnet", [ "msbuild", "/target:AtlasEFProjectMetadata", propertyArg, @@ -192,7 +192,8 @@ public void Build() args.Add("/verbosity:quiet"); args.Add("/nologo"); args.Add("/p:PublishAot=false"); // Avoid NativeAOT warnings - var exitCode = Executor.Exe.Run("dotnet", args, interceptOutput: true); + // Discard the build output, but show the errors + var exitCode = Exe.Run("dotnet", args, handleOutput: delegate(string? line) {}); if (exitCode != 0) { throw new Exception("Build failed");