From 92fbf500ddf502331b93d58a30e8544fbbe1de4b Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Tue, 16 Dec 2025 00:23:55 +0000
Subject: [PATCH 1/8] Initial plan
From 2ed9637955cd4797d74391dd8f51f57ad87a0823 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Tue, 16 Dec 2025 00:32:40 +0000
Subject: [PATCH 2/8] Update replace-text.cs to use System.CommandLine and .rsp
file support
- Added System.CommandLine package directive to replace-text.cs
- Rewrote the script to use System.CommandLine's Option and RootCommand APIs
- System.CommandLine automatically supports .rsp files via @ prefix
- Updated Aspire.ProjectTemplates.csproj to generate .rsp file with arguments
- Changed script invocation to pass .rsp file instead of command-line arguments
- This prevents command line length issues when building templates on Windows
Co-authored-by: DamianEdwards <249088+DamianEdwards@users.noreply.github.com>
---
.../Aspire.ProjectTemplates.csproj | 30 +-
tools/scripts/replace-text.cs | 290 ++++++++----------
2 files changed, 143 insertions(+), 177 deletions(-)
diff --git a/src/Aspire.ProjectTemplates/Aspire.ProjectTemplates.csproj b/src/Aspire.ProjectTemplates/Aspire.ProjectTemplates.csproj
index 8e8798f1f2f..02633e42d4d 100644
--- a/src/Aspire.ProjectTemplates/Aspire.ProjectTemplates.csproj
+++ b/src/Aspire.ProjectTemplates/Aspire.ProjectTemplates.csproj
@@ -82,6 +82,7 @@
$(_VersionBase.Split('.')[0])
$(_VersionBase.Split('.')[1])
$(VersionMajor).$(VersionMinor)
+ <_RspFilePath>$(IntermediateOutputPath)replace-text-args.rsp
@@ -121,22 +122,25 @@
-
- "@(SourceFiles, '" "')"
- "@(Replacements, '" "')"
-
-
+
-
-
-
-
-
-
-
+ <_RspLines Include="--files" />
+ <_RspLines Include="@(SourceFiles)" />
+ <_RspLines Include="--replacements" />
+ <_RspLines Include="@(Replacements)" />
-
+
+
+
+
+
diff --git a/tools/scripts/replace-text.cs b/tools/scripts/replace-text.cs
index 205b5f36aec..b5f10fa625e 100644
--- a/tools/scripts/replace-text.cs
+++ b/tools/scripts/replace-text.cs
@@ -1,211 +1,173 @@
#:package Microsoft.Extensions.FileSystemGlobbing
+#:package System.CommandLine
using System.Collections.Concurrent;
+using System.CommandLine;
using Microsoft.Extensions.FileSystemGlobbing;
using Microsoft.Extensions.FileSystemGlobbing.Abstractions;
-if (args.Length == 0 || args.Contains("--help") || args.Contains("-h"))
+var filesOption = new Option("--files")
{
- PrintUsage();
- return args.Length == 0 ? 1 : 0;
-}
+ Description = "One or more file paths, directory paths, or glob patterns",
+ AllowMultipleArgumentsPerToken = true,
+ Required = true
+};
-// Parse arguments
-var paths = new List();
-var replacements = new List<(string Find, string Replace)>();
-var currentMode = (string?)null;
-var replacementBuffer = new List();
+var replacementsOption = new Option("--replacements")
+{
+ Description = "Pairs of find/replace text values",
+ AllowMultipleArgumentsPerToken = true,
+ Required = true
+};
+
+var rootCommand = new RootCommand
+{
+ filesOption,
+ replacementsOption
+};
-for (var i = 0; i < args.Length; i++)
+rootCommand.SetAction(result =>
{
- var arg = args[i];
+ var paths = result.GetValue(filesOption) ?? Array.Empty();
+ var replacementArgs = result.GetValue(replacementsOption) ?? Array.Empty();
- if (arg == "--files")
+ // Validate and parse replacements
+ if (replacementArgs.Length == 0)
{
- currentMode = "files";
- continue;
+ Console.Error.WriteLine("Error: No replacements provided. Use --replacements to specify find/replace pairs.");
+ Environment.Exit(1);
}
- else if (arg == "--replacements")
+
+ if (replacementArgs.Length % 2 != 0)
{
- currentMode = "replacements";
- continue;
+ Console.Error.WriteLine($"Error: Replacement arguments must be provided in pairs (find, replace).");
+ Console.Error.WriteLine($" Received {replacementArgs.Length} arguments after --replacements.");
+ Environment.Exit(1);
}
- if (currentMode == "files")
+ var replacements = new List<(string Find, string Replace)>();
+ for (var i = 0; i < replacementArgs.Length; i += 2)
{
- paths.Add(arg);
+ var find = replacementArgs[i];
+ var replace = replacementArgs[i + 1];
+
+ if (string.IsNullOrEmpty(find))
+ {
+ Console.Error.WriteLine($"Error: Find text at position {i + 1} in --replacements cannot be empty.");
+ Environment.Exit(1);
+ }
+
+ replacements.Add((find, replace));
}
- else if (currentMode == "replacements")
+
+ Console.WriteLine($"Paths: {paths.Length}");
+ foreach (var path in paths)
{
- replacementBuffer.Add(arg);
+ Console.WriteLine($" '{path}'");
}
- else
+ Console.WriteLine($"Replacements: {replacements.Count}");
+ foreach (var (find, replace) in replacements)
{
- Console.Error.WriteLine($"Error: Unexpected argument '{arg}'. Use --files or --replacements to specify argument type.");
- return 1;
+ Console.WriteLine($" '{find}' -> '{replace}'");
}
-}
-
-// Validate paths
-if (paths.Count == 0)
-{
- Console.Error.WriteLine("Error: No file paths provided. Use --files to specify paths.");
- PrintUsage();
- return 1;
-}
-
-// Validate and parse replacements
-if (replacementBuffer.Count == 0)
-{
- Console.Error.WriteLine("Error: No replacements provided. Use --replacements to specify find/replace pairs.");
- PrintUsage();
- return 1;
-}
+ Console.WriteLine();
-if (replacementBuffer.Count % 2 != 0)
-{
- Console.Error.WriteLine($"Error: Replacement arguments must be provided in pairs (find, replace).");
- Console.Error.WriteLine($" Received {replacementBuffer.Count} arguments after --replacements.");
- return 1;
-}
+ var filesToProcess = new HashSet(StringComparer.OrdinalIgnoreCase);
-for (var i = 0; i < replacementBuffer.Count; i += 2)
-{
- var find = replacementBuffer[i];
- var replace = replacementBuffer[i + 1];
+ var matcher = new Matcher();
+ var hasGlobPatterns = false;
- if (string.IsNullOrEmpty(find))
+ foreach (var pathValue in paths)
{
- Console.Error.WriteLine($"Error: Find text at position {i + 1} in --replacements cannot be empty.");
- return 1;
+ if (File.Exists(pathValue))
+ {
+ // If it's a direct file path add it as is
+ filesToProcess.Add(Path.GetFullPath(pathValue));
+ }
+ else if (Directory.Exists(pathValue))
+ {
+ // If it's a directory, include all files within it
+ matcher.AddInclude(Path.Combine(pathValue, "**/*"));
+ hasGlobPatterns = true;
+ }
+ else if (pathValue.Contains('*') || pathValue.Contains('?'))
+ {
+ matcher.AddInclude(pathValue);
+ hasGlobPatterns = true;
+ }
}
- replacements.Add((find, replace));
-}
+ var currentDirectory = Directory.GetCurrentDirectory();
-Console.WriteLine($"Paths: {paths.Count}");
-foreach (var path in paths)
-{
- Console.WriteLine($" '{path}'");
-}
-Console.WriteLine($"Replacements: {replacements.Count}");
-foreach (var (find, replace) in replacements)
-{
- Console.WriteLine($" '{find}' -> '{replace}'");
-}
-Console.WriteLine();
-
-var filesToProcess = new HashSet(StringComparer.OrdinalIgnoreCase);
-
-var matcher = new Matcher();
-var hasGlobPatterns = false;
-
-foreach (var pathValue in paths)
-{
- if (File.Exists(pathValue))
- {
- // If it's a direct file path add it as is
- filesToProcess.Add(Path.GetFullPath(pathValue));
- }
- else if (Directory.Exists(pathValue))
+ if (hasGlobPatterns)
{
- // If it's a directory, include all files within it
- matcher.AddInclude(Path.Combine(pathValue, "**/*"));
- hasGlobPatterns = true;
- }
- else if (pathValue.Contains('*') || pathValue.Contains('?'))
- {
- matcher.AddInclude(pathValue);
- hasGlobPatterns = true;
- }
-}
-
-var currentDirectory = Directory.GetCurrentDirectory();
+ // Collect files from glob matching
+ var directoryInfo = new DirectoryInfoWrapper(new DirectoryInfo(currentDirectory));
+ var matchResult = matcher.Execute(directoryInfo);
-if (hasGlobPatterns)
-{
- // Collect files from glob matching
- var directoryInfo = new DirectoryInfoWrapper(new DirectoryInfo(currentDirectory));
- var matchResult = matcher.Execute(directoryInfo);
+ foreach (var file in matchResult.Files)
+ {
+ filesToProcess.Add(Path.GetFullPath(Path.Combine(currentDirectory, file.Path)));
+ }
+ }
- foreach (var file in matchResult.Files)
+ if (filesToProcess.Count == 0)
{
- filesToProcess.Add(Path.GetFullPath(Path.Combine(currentDirectory, file.Path)));
+ Console.WriteLine("No files matched the provided paths.");
+ Environment.Exit(0);
}
-}
-if (filesToProcess.Count == 0)
-{
- Console.WriteLine("No files matched the provided paths.");
- return 0;
-}
-
-Console.WriteLine($"Found {filesToProcess.Count} file(s) matching the provided paths.");
-Console.WriteLine();
+ Console.WriteLine($"Found {filesToProcess.Count} file(s) matching the provided paths.");
+ Console.WriteLine();
-var processedCount = 0;
-var modifiedCount = 0;
-var errorCount = 0;
-var errors = new ConcurrentBag<(string File, string Error)>();
+ var processedCount = 0;
+ var modifiedCount = 0;
+ var errorCount = 0;
+ var errors = new ConcurrentBag<(string File, string Error)>();
-Parallel.ForEach(filesToProcess, new ParallelOptions { MaxDegreeOfParallelism = Environment.ProcessorCount }, filePath =>
-{
- try
+ Parallel.ForEach(filesToProcess, new ParallelOptions { MaxDegreeOfParallelism = Environment.ProcessorCount }, filePath =>
{
- var content = File.ReadAllText(filePath);
- var originalContent = content;
-
- foreach (var (find, replace) in replacements)
+ try
{
- content = content.Replace(find, replace, StringComparison.Ordinal);
+ var content = File.ReadAllText(filePath);
+ var originalContent = content;
+
+ foreach (var (find, replace) in replacements)
+ {
+ content = content.Replace(find, replace, StringComparison.Ordinal);
+ }
+
+ if (!string.Equals(content, originalContent, StringComparison.Ordinal))
+ {
+ File.WriteAllText(filePath, content);
+ Interlocked.Increment(ref modifiedCount);
+ Console.WriteLine($"Modified: {Path.GetRelativePath(currentDirectory, filePath)}");
+ }
+
+ Interlocked.Increment(ref processedCount);
}
-
- if (!string.Equals(content, originalContent, StringComparison.Ordinal))
+ catch (Exception ex)
{
- File.WriteAllText(filePath, content);
- Interlocked.Increment(ref modifiedCount);
- Console.WriteLine($"Modified: {Path.GetRelativePath(currentDirectory, filePath)}");
+ Interlocked.Increment(ref errorCount);
+ errors.Add((filePath, ex.Message));
}
+ });
- Interlocked.Increment(ref processedCount);
- }
- catch (Exception ex)
- {
- Interlocked.Increment(ref errorCount);
- errors.Add((filePath, ex.Message));
- }
-});
-
-Console.WriteLine();
-Console.WriteLine($"Processed: {processedCount} file(s)");
-Console.WriteLine($"Modified: {modifiedCount} file(s)");
-
-if (errorCount > 0)
-{
- Console.WriteLine($"Errors: {errorCount} file(s)");
Console.WriteLine();
- Console.Error.WriteLine("Errors encountered:");
- foreach (var (file, error) in errors)
+ Console.WriteLine($"Processed: {processedCount} file(s)");
+ Console.WriteLine($"Modified: {modifiedCount} file(s)");
+
+ if (errorCount > 0)
{
- Console.Error.WriteLine($" {Path.GetRelativePath(currentDirectory, file)}: {error}");
+ Console.WriteLine($"Errors: {errorCount} file(s)");
+ Console.WriteLine();
+ Console.Error.WriteLine("Errors encountered:");
+ foreach (var (file, error) in errors)
+ {
+ Console.Error.WriteLine($" {Path.GetRelativePath(currentDirectory, file)}: {error}");
+ }
+ Environment.Exit(1);
}
- return 1;
-}
-
-return 0;
-
-static void PrintUsage()
-{
- Console.Error.WriteLine("""
- Usage: dotnet replace-text.cs --files [path2] ... --replacements [ ...]
-
- Arguments:
- --files One or more file paths, directory paths, or glob patterns
- --replacements Pairs of find/replace text values
-
- Examples:
- dotnet replace-text.cs --files "./src/**/*.cs" "./src/**/*.csproj" --replacements "!!VERSION!!" "7.0.5" "!!MAJOR_MINOR!!" "7.0"
- dotnet replace-text.cs --files ./path/to/file.cs --replacements "oldText" "newText"
- """);
-}
+});
+return rootCommand.Parse(args).Invoke();
From 58469573371b1c1380f96814a8af1b796202f640 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Tue, 16 Dec 2025 00:35:26 +0000
Subject: [PATCH 3/8] Improve error handling in replace-text.cs script
- Replace Environment.Exit() calls with proper return statements
- Add try-catch block around the entire action handler
- Return exit codes from the action handler instead of calling Environment.Exit()
- This allows proper cleanup and makes the script more testable
Co-authored-by: DamianEdwards <249088+DamianEdwards@users.noreply.github.com>
---
tools/scripts/replace-text.cs | 146 ++++++++++++++++++----------------
1 file changed, 78 insertions(+), 68 deletions(-)
diff --git a/tools/scripts/replace-text.cs b/tools/scripts/replace-text.cs
index b5f10fa625e..79d893e71cc 100644
--- a/tools/scripts/replace-text.cs
+++ b/tools/scripts/replace-text.cs
@@ -28,37 +28,39 @@
rootCommand.SetAction(result =>
{
- var paths = result.GetValue(filesOption) ?? Array.Empty();
- var replacementArgs = result.GetValue(replacementsOption) ?? Array.Empty();
-
- // Validate and parse replacements
- if (replacementArgs.Length == 0)
+ try
{
- Console.Error.WriteLine("Error: No replacements provided. Use --replacements to specify find/replace pairs.");
- Environment.Exit(1);
- }
-
- if (replacementArgs.Length % 2 != 0)
- {
- Console.Error.WriteLine($"Error: Replacement arguments must be provided in pairs (find, replace).");
- Console.Error.WriteLine($" Received {replacementArgs.Length} arguments after --replacements.");
- Environment.Exit(1);
- }
+ var paths = result.GetValue(filesOption) ?? Array.Empty();
+ var replacementArgs = result.GetValue(replacementsOption) ?? Array.Empty();
- var replacements = new List<(string Find, string Replace)>();
- for (var i = 0; i < replacementArgs.Length; i += 2)
- {
- var find = replacementArgs[i];
- var replace = replacementArgs[i + 1];
+ // Validate and parse replacements
+ if (replacementArgs.Length == 0)
+ {
+ Console.Error.WriteLine("Error: No replacements provided. Use --replacements to specify find/replace pairs.");
+ return 1;
+ }
- if (string.IsNullOrEmpty(find))
+ if (replacementArgs.Length % 2 != 0)
{
- Console.Error.WriteLine($"Error: Find text at position {i + 1} in --replacements cannot be empty.");
- Environment.Exit(1);
+ Console.Error.WriteLine($"Error: Replacement arguments must be provided in pairs (find, replace).");
+ Console.Error.WriteLine($" Received {replacementArgs.Length} arguments after --replacements.");
+ return 1;
}
- replacements.Add((find, replace));
- }
+ var replacements = new List<(string Find, string Replace)>();
+ for (var i = 0; i < replacementArgs.Length; i += 2)
+ {
+ var find = replacementArgs[i];
+ var replace = replacementArgs[i + 1];
+
+ if (string.IsNullOrEmpty(find))
+ {
+ Console.Error.WriteLine($"Error: Find text at position {i + 1} in --replacements cannot be empty.");
+ return 1;
+ }
+
+ replacements.Add((find, replace));
+ }
Console.WriteLine($"Paths: {paths.Length}");
foreach (var path in paths)
@@ -111,62 +113,70 @@
}
}
- if (filesToProcess.Count == 0)
- {
- Console.WriteLine("No files matched the provided paths.");
- Environment.Exit(0);
- }
+ if (filesToProcess.Count == 0)
+ {
+ Console.WriteLine("No files matched the provided paths.");
+ return 0;
+ }
- Console.WriteLine($"Found {filesToProcess.Count} file(s) matching the provided paths.");
- Console.WriteLine();
+ Console.WriteLine($"Found {filesToProcess.Count} file(s) matching the provided paths.");
+ Console.WriteLine();
- var processedCount = 0;
- var modifiedCount = 0;
- var errorCount = 0;
- var errors = new ConcurrentBag<(string File, string Error)>();
+ var processedCount = 0;
+ var modifiedCount = 0;
+ var errorCount = 0;
+ var errors = new ConcurrentBag<(string File, string Error)>();
- Parallel.ForEach(filesToProcess, new ParallelOptions { MaxDegreeOfParallelism = Environment.ProcessorCount }, filePath =>
- {
- try
+ Parallel.ForEach(filesToProcess, new ParallelOptions { MaxDegreeOfParallelism = Environment.ProcessorCount }, filePath =>
{
- var content = File.ReadAllText(filePath);
- var originalContent = content;
-
- foreach (var (find, replace) in replacements)
+ try
{
- content = content.Replace(find, replace, StringComparison.Ordinal);
+ var content = File.ReadAllText(filePath);
+ var originalContent = content;
+
+ foreach (var (find, replace) in replacements)
+ {
+ content = content.Replace(find, replace, StringComparison.Ordinal);
+ }
+
+ if (!string.Equals(content, originalContent, StringComparison.Ordinal))
+ {
+ File.WriteAllText(filePath, content);
+ Interlocked.Increment(ref modifiedCount);
+ Console.WriteLine($"Modified: {Path.GetRelativePath(currentDirectory, filePath)}");
+ }
+
+ Interlocked.Increment(ref processedCount);
}
-
- if (!string.Equals(content, originalContent, StringComparison.Ordinal))
+ catch (Exception ex)
{
- File.WriteAllText(filePath, content);
- Interlocked.Increment(ref modifiedCount);
- Console.WriteLine($"Modified: {Path.GetRelativePath(currentDirectory, filePath)}");
+ Interlocked.Increment(ref errorCount);
+ errors.Add((filePath, ex.Message));
}
+ });
- Interlocked.Increment(ref processedCount);
- }
- catch (Exception ex)
+ Console.WriteLine();
+ Console.WriteLine($"Processed: {processedCount} file(s)");
+ Console.WriteLine($"Modified: {modifiedCount} file(s)");
+
+ if (errorCount > 0)
{
- Interlocked.Increment(ref errorCount);
- errors.Add((filePath, ex.Message));
+ Console.WriteLine($"Errors: {errorCount} file(s)");
+ Console.WriteLine();
+ Console.Error.WriteLine("Errors encountered:");
+ foreach (var (file, error) in errors)
+ {
+ Console.Error.WriteLine($" {Path.GetRelativePath(currentDirectory, file)}: {error}");
+ }
+ return 1;
}
- });
-
- Console.WriteLine();
- Console.WriteLine($"Processed: {processedCount} file(s)");
- Console.WriteLine($"Modified: {modifiedCount} file(s)");
- if (errorCount > 0)
+ return 0;
+ }
+ catch (Exception ex)
{
- Console.WriteLine($"Errors: {errorCount} file(s)");
- Console.WriteLine();
- Console.Error.WriteLine("Errors encountered:");
- foreach (var (file, error) in errors)
- {
- Console.Error.WriteLine($" {Path.GetRelativePath(currentDirectory, file)}: {error}");
- }
- Environment.Exit(1);
+ Console.Error.WriteLine($"Unexpected error: {ex.Message}");
+ return 1;
}
});
From c3c1237be5a17bb060fca9b0269d528e1802e00b Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Tue, 16 Dec 2025 02:08:09 +0000
Subject: [PATCH 4/8] Build replace-text.cs to executable before running to
avoid dotnet CLI expanding .rsp
The dotnet CLI itself uses System.CommandLine and expands .rsp files before passing
arguments, which means we still hit the command line limit when using 'dotnet script.cs'.
Now the build process:
1. Builds the script to an executable using 'dotnet build'
2. Runs the compiled executable directly with '@response.rsp'
3. This avoids the dotnet CLI intermediary and prevents .rsp expansion
The compiled executable is placed in artifacts/bin/replace-text/Debug/
Co-authored-by: DamianEdwards <249088+DamianEdwards@users.noreply.github.com>
---
args.rsp | 6 ++++++
.../Aspire.ProjectTemplates.csproj | 13 +++++++++++--
test2.txt | 1 +
3 files changed, 18 insertions(+), 2 deletions(-)
create mode 100644 args.rsp
create mode 100644 test2.txt
diff --git a/args.rsp b/args.rsp
new file mode 100644
index 00000000000..e4834568ef2
--- /dev/null
+++ b/args.rsp
@@ -0,0 +1,6 @@
+--files
+/tmp/test-replace/test1.txt
+/tmp/test-replace/test2.txt
+--replacements
+!!VERSION!!
+4.0.0
diff --git a/src/Aspire.ProjectTemplates/Aspire.ProjectTemplates.csproj b/src/Aspire.ProjectTemplates/Aspire.ProjectTemplates.csproj
index 02633e42d4d..4191e154a9d 100644
--- a/src/Aspire.ProjectTemplates/Aspire.ProjectTemplates.csproj
+++ b/src/Aspire.ProjectTemplates/Aspire.ProjectTemplates.csproj
@@ -83,6 +83,9 @@
$(_VersionBase.Split('.')[1])
$(VersionMajor).$(VersionMinor)
<_RspFilePath>$(IntermediateOutputPath)replace-text-args.rsp
+ <_ReplaceTextScriptPath>$(RepoRoot)tools/scripts/replace-text.cs
+ <_ReplaceTextExePath>$(RepoRoot)artifacts/bin/replace-text/Debug/replace-text
+ <_ReplaceTextExePath Condition="'$(OS)' == 'Windows_NT'">$(_ReplaceTextExePath).exe
@@ -136,8 +139,14 @@
Overwrite="true"
WriteOnlyWhenDifferent="true" />
-
-
+
+
+
+
diff --git a/test2.txt b/test2.txt
new file mode 100644
index 00000000000..d05f456af0e
--- /dev/null
+++ b/test2.txt
@@ -0,0 +1 @@
+Version: !!VERSION!!
From e89b8f71dc45538110c642fe1a18c517fdb160f5 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Tue, 16 Dec 2025 02:08:51 +0000
Subject: [PATCH 5/8] Remove accidentally committed test files
Co-authored-by: DamianEdwards <249088+DamianEdwards@users.noreply.github.com>
---
args.rsp | 6 ------
test2.txt | 1 -
2 files changed, 7 deletions(-)
delete mode 100644 args.rsp
delete mode 100644 test2.txt
diff --git a/args.rsp b/args.rsp
deleted file mode 100644
index e4834568ef2..00000000000
--- a/args.rsp
+++ /dev/null
@@ -1,6 +0,0 @@
---files
-/tmp/test-replace/test1.txt
-/tmp/test-replace/test2.txt
---replacements
-!!VERSION!!
-4.0.0
diff --git a/test2.txt b/test2.txt
deleted file mode 100644
index d05f456af0e..00000000000
--- a/test2.txt
+++ /dev/null
@@ -1 +0,0 @@
-Version: !!VERSION!!
From 3e135ea57974b5e41ec80b2d77fd37dda50fe3f0 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Tue, 16 Dec 2025 05:52:22 +0000
Subject: [PATCH 6/8] Use dotnet script.cs with -- to avoid CLI expanding .rsp
file
Per feedback, the simpler approach is to use 'dotnet script.cs -- @response.rsp'
where the '--' tells dotnet CLI to pass arguments directly to the script without
interpretation. This avoids the CLI expanding the .rsp file and hitting command
line limits.
The script still needs to be built once (dotnet does this automatically when
running .cs files), so we keep the build step to ensure it's compiled before use.
Co-authored-by: DamianEdwards <249088+DamianEdwards@users.noreply.github.com>
---
.../Aspire.ProjectTemplates.csproj | 8 +++-----
1 file changed, 3 insertions(+), 5 deletions(-)
diff --git a/src/Aspire.ProjectTemplates/Aspire.ProjectTemplates.csproj b/src/Aspire.ProjectTemplates/Aspire.ProjectTemplates.csproj
index 4191e154a9d..b73f8e25fe4 100644
--- a/src/Aspire.ProjectTemplates/Aspire.ProjectTemplates.csproj
+++ b/src/Aspire.ProjectTemplates/Aspire.ProjectTemplates.csproj
@@ -84,8 +84,6 @@
$(VersionMajor).$(VersionMinor)
<_RspFilePath>$(IntermediateOutputPath)replace-text-args.rsp
<_ReplaceTextScriptPath>$(RepoRoot)tools/scripts/replace-text.cs
- <_ReplaceTextExePath>$(RepoRoot)artifacts/bin/replace-text/Debug/replace-text
- <_ReplaceTextExePath Condition="'$(OS)' == 'Windows_NT'">$(_ReplaceTextExePath).exe
@@ -139,14 +137,14 @@
Overwrite="true"
WriteOnlyWhenDifferent="true" />
-
+
-
-
+
From 8d3665066cdba61c1843a75d4de563867e1d5ca9 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Tue, 16 Dec 2025 05:59:47 +0000
Subject: [PATCH 7/8] Remove explicit build step for replace-text script
The build step is not needed. When using 'dotnet script.cs -- @response.rsp',
dotnet automatically compiles and caches the script as needed. The explicit
build step was redundant.
Co-authored-by: DamianEdwards <249088+DamianEdwards@users.noreply.github.com>
---
src/Aspire.ProjectTemplates/Aspire.ProjectTemplates.csproj | 6 ------
1 file changed, 6 deletions(-)
diff --git a/src/Aspire.ProjectTemplates/Aspire.ProjectTemplates.csproj b/src/Aspire.ProjectTemplates/Aspire.ProjectTemplates.csproj
index b73f8e25fe4..5428797b2cf 100644
--- a/src/Aspire.ProjectTemplates/Aspire.ProjectTemplates.csproj
+++ b/src/Aspire.ProjectTemplates/Aspire.ProjectTemplates.csproj
@@ -137,12 +137,6 @@
Overwrite="true"
WriteOnlyWhenDifferent="true" />
-
-
-
Date: Tue, 16 Dec 2025 10:28:06 -0800
Subject: [PATCH 8/8] Fix formatting
---
tools/scripts/replace-text.cs | 80 +++++++++++++++++------------------
1 file changed, 40 insertions(+), 40 deletions(-)
diff --git a/tools/scripts/replace-text.cs b/tools/scripts/replace-text.cs
index 79d893e71cc..dcfc1222c13 100644
--- a/tools/scripts/replace-text.cs
+++ b/tools/scripts/replace-text.cs
@@ -62,56 +62,56 @@
replacements.Add((find, replace));
}
- Console.WriteLine($"Paths: {paths.Length}");
- foreach (var path in paths)
- {
- Console.WriteLine($" '{path}'");
- }
- Console.WriteLine($"Replacements: {replacements.Count}");
- foreach (var (find, replace) in replacements)
- {
- Console.WriteLine($" '{find}' -> '{replace}'");
- }
- Console.WriteLine();
-
- var filesToProcess = new HashSet(StringComparer.OrdinalIgnoreCase);
-
- var matcher = new Matcher();
- var hasGlobPatterns = false;
-
- foreach (var pathValue in paths)
- {
- if (File.Exists(pathValue))
+ Console.WriteLine($"Paths: {paths.Length}");
+ foreach (var path in paths)
{
- // If it's a direct file path add it as is
- filesToProcess.Add(Path.GetFullPath(pathValue));
+ Console.WriteLine($" '{path}'");
}
- else if (Directory.Exists(pathValue))
+ Console.WriteLine($"Replacements: {replacements.Count}");
+ foreach (var (find, replace) in replacements)
{
- // If it's a directory, include all files within it
- matcher.AddInclude(Path.Combine(pathValue, "**/*"));
- hasGlobPatterns = true;
+ Console.WriteLine($" '{find}' -> '{replace}'");
}
- else if (pathValue.Contains('*') || pathValue.Contains('?'))
+ Console.WriteLine();
+
+ var filesToProcess = new HashSet(StringComparer.OrdinalIgnoreCase);
+
+ var matcher = new Matcher();
+ var hasGlobPatterns = false;
+
+ foreach (var pathValue in paths)
{
- matcher.AddInclude(pathValue);
- hasGlobPatterns = true;
+ if (File.Exists(pathValue))
+ {
+ // If it's a direct file path add it as is
+ filesToProcess.Add(Path.GetFullPath(pathValue));
+ }
+ else if (Directory.Exists(pathValue))
+ {
+ // If it's a directory, include all files within it
+ matcher.AddInclude(Path.Combine(pathValue, "**/*"));
+ hasGlobPatterns = true;
+ }
+ else if (pathValue.Contains('*') || pathValue.Contains('?'))
+ {
+ matcher.AddInclude(pathValue);
+ hasGlobPatterns = true;
+ }
}
- }
- var currentDirectory = Directory.GetCurrentDirectory();
+ var currentDirectory = Directory.GetCurrentDirectory();
- if (hasGlobPatterns)
- {
- // Collect files from glob matching
- var directoryInfo = new DirectoryInfoWrapper(new DirectoryInfo(currentDirectory));
- var matchResult = matcher.Execute(directoryInfo);
-
- foreach (var file in matchResult.Files)
+ if (hasGlobPatterns)
{
- filesToProcess.Add(Path.GetFullPath(Path.Combine(currentDirectory, file.Path)));
+ // Collect files from glob matching
+ var directoryInfo = new DirectoryInfoWrapper(new DirectoryInfo(currentDirectory));
+ var matchResult = matcher.Execute(directoryInfo);
+
+ foreach (var file in matchResult.Files)
+ {
+ filesToProcess.Add(Path.GetFullPath(Path.Combine(currentDirectory, file.Path)));
+ }
}
- }
if (filesToProcess.Count == 0)
{