-
-
Notifications
You must be signed in to change notification settings - Fork 64
Add support for systems running only .NET 9.0 (without .NET 8.0) in Refitter.MSBuild #746
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -60,24 +60,28 @@ public override bool Execute() | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| private List<string> StartProcess(string file) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| var expectedFiles = GetExpectedGeneratedFiles(file); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| var expectedFiles = GetExpectedGeneratedFiles(file); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| var assembly = Assembly.GetExecutingAssembly(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| var packageFolder = Path.GetDirectoryName(assembly.Location); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| var seperator = Path.DirectorySeparatorChar; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| var refitterDll = $"{packageFolder}{seperator}..{seperator}refitter.dll"; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| var refitterDll = $"{packageFolder}{seperator}..{seperator}net8.0{seperator}refitter.dll"; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| var args = $"{refitterDll} --settings-file {file}"; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (DisableLogging) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| List<string> installedRuntimes = GetInstalledDotnetRuntimes(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (installedRuntimes.Any(r => r.StartsWith("Microsoft.NETCore.App 9."))) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| args += " --no-logging"; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Use .NET 9 version if available | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| refitterDll = $"{packageFolder}{seperator}..{seperator}net9.0{seperator}refitter.dll"; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| TryLogCommandLine("Detected .NET 9 runtime. Using .NET 9 version of Refitter."); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| else | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| TryLogCommandLine("Using .NET 8 version of Refitter."); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (!File.Exists(refitterDll)) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| var args = $"{refitterDll} --settings-file {file}"; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (DisableLogging) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| TryLogError($"Refitter CLI not found at: {refitterDll}"); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| TryLogError($"Assembly location: {assembly.Location}"); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| TryLogError($"Package folder: {packageFolder}"); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return new List<string>(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| args += " --no-logging"; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+81
to
85
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| TryLogCommandLine($"Starting dotnet {args}"); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -108,6 +112,29 @@ private List<string> StartProcess(string file) | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return expectedFiles.Where(File.Exists).ToList(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| private static List<string> GetInstalledDotnetRuntimes() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| var installedRuntimes = new List<string>(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| using (var process = new Process()) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| process.StartInfo.FileName = "dotnet"; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| process.StartInfo.Arguments = "--list-runtimes"; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| process.StartInfo.RedirectStandardOutput = true; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| process.StartInfo.UseShellExecute = false; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| process.StartInfo.CreateNoWindow = true; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| process.Start(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| using (var reader = process.StandardOutput) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| var output = reader.ReadToEnd(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| installedRuntimes.AddRange(output?.Split([Environment.NewLine], StringSplitOptions.RemoveEmptyEntries)); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| installedRuntimes.AddRange(output?.Split([Environment.NewLine], StringSplitOptions.RemoveEmptyEntries)); | |
| installedRuntimes.AddRange(output?.Split([Environment.NewLine], StringSplitOptions.RemoveEmptyEntries) ?? Array.Empty<string>()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Potential NullReferenceException when splitting output.
The null-conditional operator ?. is used with Split, but the result is then passed to AddRange which doesn't handle null gracefully.
Apply this diff to handle potential null output:
- installedRuntimes.AddRange(output?.Split([Environment.NewLine], StringSplitOptions.RemoveEmptyEntries));
+ if (!string.IsNullOrEmpty(output))
+ {
+ installedRuntimes.AddRange(output.Split([Environment.NewLine], StringSplitOptions.RemoveEmptyEntries));
+ }📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| installedRuntimes.AddRange(output?.Split([Environment.NewLine], StringSplitOptions.RemoveEmptyEntries)); | |
| if (!string.IsNullOrEmpty(output)) | |
| { | |
| installedRuntimes.AddRange(output.Split(new[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries)); | |
| } |
🤖 Prompt for AI Agents
In src/Refitter.MSBuild/RefitterGenerateTask.cs around line 130, the code calls
AddRange(output?.Split([Environment.NewLine],
StringSplitOptions.RemoveEmptyEntries)) which can pass null to AddRange if
output is null; change it so AddRange receives a non-null sequence (for example
use the null-coalescing operator to supply Array.Empty<string>() or an empty
enumerable when output is null) so AddRange is never called with a null
argument.
Copilot
AI
Sep 12, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The method doesn't handle process execution failures or capture stderr output. If the 'dotnet' command fails or isn't found, the method will silently return an empty list, causing the runtime detection to fail without proper error reporting.
| private static List<string> GetInstalledDotnetRuntimes() | |
| { | |
| var installedRuntimes = new List<string>(); | |
| using (var process = new Process()) | |
| { | |
| process.StartInfo.FileName = "dotnet"; | |
| process.StartInfo.Arguments = "--list-runtimes"; | |
| process.StartInfo.RedirectStandardOutput = true; | |
| process.StartInfo.UseShellExecute = false; | |
| process.StartInfo.CreateNoWindow = true; | |
| process.Start(); | |
| using (var reader = process.StandardOutput) | |
| { | |
| var output = reader.ReadToEnd(); | |
| installedRuntimes.AddRange(output?.Split([Environment.NewLine], StringSplitOptions.RemoveEmptyEntries)); | |
| } | |
| process.WaitForExit(); | |
| } | |
| private List<string> GetInstalledDotnetRuntimes() | |
| { | |
| var installedRuntimes = new List<string>(); | |
| try | |
| { | |
| using (var process = new Process()) | |
| { | |
| process.StartInfo.FileName = "dotnet"; | |
| process.StartInfo.Arguments = "--list-runtimes"; | |
| process.StartInfo.RedirectStandardOutput = true; | |
| process.StartInfo.RedirectStandardError = true; | |
| process.StartInfo.UseShellExecute = false; | |
| process.StartInfo.CreateNoWindow = true; | |
| process.Start(); | |
| string output = process.StandardOutput.ReadToEnd(); | |
| string error = process.StandardError.ReadToEnd(); | |
| process.WaitForExit(); | |
| if (process.ExitCode != 0) | |
| { | |
| TryLogError($"Failed to execute 'dotnet --list-runtimes'. Exit code: {process.ExitCode}. Error: {error}"); | |
| return new List<string>(); | |
| } | |
| if (!string.IsNullOrWhiteSpace(error)) | |
| { | |
| TryLogError($"Error output from 'dotnet --list-runtimes': {error}"); | |
| } | |
| installedRuntimes.AddRange(output?.Split([Environment.NewLine], StringSplitOptions.RemoveEmptyEntries)); | |
| } | |
| } | |
| catch (Exception ex) | |
| { | |
| TryLogError($"Exception while executing 'dotnet --list-runtimes': {ex.Message}"); | |
| return new List<string>(); | |
| } |
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,22 @@ | ||||||||||||||||||||
| #!/bin/bash | ||||||||||||||||||||
|
|
||||||||||||||||||||
| rm -rf bin | ||||||||||||||||||||
| rm -rf obj | ||||||||||||||||||||
| dotnet build-server shutdown | ||||||||||||||||||||
| dotnet nuget locals global-packages --clear | ||||||||||||||||||||
| rm -f Refitter.MSBuild.*.nupkg | ||||||||||||||||||||
| rm -f Petstore.cs | ||||||||||||||||||||
| dotnet restore ../../src/Refitter.sln | ||||||||||||||||||||
| dotnet clean -c release ../../src/Refitter.sln | ||||||||||||||||||||
| dotnet build -c release ../../src/Refitter/Refitter.csproj | ||||||||||||||||||||
| dotnet build -c release ../../src/Refitter.MSBuild/Refitter.MSBuild.csproj | ||||||||||||||||||||
| dotnet pack -c release ../../src/Refitter.MSBuild/Refitter.MSBuild.csproj -o . | ||||||||||||||||||||
|
|
||||||||||||||||||||
| # Find the nupkg file and add it as a package | ||||||||||||||||||||
| find . -name "Refitter.MSBuild.*.nupkg" -exec dotnet add package {} --source . \; | ||||||||||||||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The find command may fail if no .nupkg files exist. The Apply this diff to handle the case when no packages are found: # Find the nupkg file and add it as a package
-find . -name "Refitter.MSBuild.*.nupkg" -exec dotnet add package {} --source . \;
+NUPKG_FILES=$(find . -name "Refitter.MSBuild.*.nupkg" 2>/dev/null || true)
+if [ -n "$NUPKG_FILES" ]; then
+ echo "$NUPKG_FILES" | xargs -I {} dotnet add package {} --source .
+else
+ echo "Error: No .nupkg files found after packing"
+ exit 1
+fi📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||
|
|
||||||||||||||||||||
| dotnet restore | ||||||||||||||||||||
| dotnet add package Refitter.MSBuild --source . | ||||||||||||||||||||
| dotnet run -v d -filelogger | ||||||||||||||||||||
| dotnet remove package Refitter.MSBuild | ||||||||||||||||||||
| rm -f Refitter.MSBuild.*.nupkg | ||||||||||||||||||||
|
Comment on lines
+1
to
+22
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Add error handling and make the script more robust. The script lacks error handling which could lead to silent failures or incomplete cleanup. Consider adding Apply this diff to add error handling: #!/bin/bash
+set -e # Exit on error
+
+# Trap to ensure cleanup even on failure
+trap 'echo "Build failed. Cleaning up..."; rm -f Refitter.MSBuild.*.nupkg' ERR
rm -rf bin
rm -rf objAlso consider checking if required tools are available: # Check required tools
for cmd in dotnet find; do
if ! command -v $cmd &> /dev/null; then
echo "Error: $cmd is not installed"
exit 1
fi
done🤖 Prompt for AI Agents |
||||||||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Add fallback for when the dotnet command fails to detect runtimes.
The runtime detection could fail if the
dotnetcommand is not available or returns an error. Consider adding error handling.Apply this diff to add error handling:
var refitterDll = $"{packageFolder}{seperator}..{seperator}net8.0{seperator}refitter.dll"; - List<string> installedRuntimes = GetInstalledDotnetRuntimes(); - if (installedRuntimes.Any(r => r.StartsWith("Microsoft.NETCore.App 9."))) + try { - // Use .NET 9 version if available - refitterDll = $"{packageFolder}{seperator}..{seperator}net9.0{seperator}refitter.dll"; - TryLogCommandLine("Detected .NET 9 runtime. Using .NET 9 version of Refitter."); + List<string> installedRuntimes = GetInstalledDotnetRuntimes(); + if (installedRuntimes.Any(r => r.StartsWith("Microsoft.NETCore.App 9."))) + { + // Use .NET 9 version if available + refitterDll = $"{packageFolder}{seperator}..{seperator}net9.0{seperator}refitter.dll"; + TryLogCommandLine("Detected .NET 9 runtime. Using .NET 9 version of Refitter."); + } + else + { + TryLogCommandLine("Using .NET 8 version of Refitter."); + } } - else + catch (Exception ex) { - TryLogCommandLine("Using .NET 8 version of Refitter."); + TryLogCommandLine($"Failed to detect .NET runtimes: {ex.Message}. Defaulting to .NET 8 version."); }📝 Committable suggestion
🤖 Prompt for AI Agents