From f08d91bcf282ce031897e24626e2133e55c9be9b Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 11 Feb 2026 00:07:55 +0000 Subject: [PATCH 1/3] Initial plan From 689f734e3630a7af6fc355911787da9bf4b46b07 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 11 Feb 2026 00:13:15 +0000 Subject: [PATCH 2/3] =?UTF-8?q?refactor(api):=20=E2=99=BB=EF=B8=8F=20added?= =?UTF-8?q?=20StringExtensions=20with=20SplitByDelimiters=20method?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Created centralized extension method for delimited string parsing with escape character support. Co-authored-by: caunt <5324218+caunt@users.noreply.github.com> --- src/Api/Extensions/StringExtensions.cs | 63 ++++++++ .../Nuget/NuGetDependencyResolver.cs | 8 +- src/Platform/Plugins/PluginService.cs | 3 +- .../ExtensionsTests/StringExtensionsTests.cs | 135 ++++++++++++++++++ 4 files changed, 203 insertions(+), 6 deletions(-) create mode 100644 src/Api/Extensions/StringExtensions.cs create mode 100644 src/Tests/ExtensionsTests/StringExtensionsTests.cs diff --git a/src/Api/Extensions/StringExtensions.cs b/src/Api/Extensions/StringExtensions.cs new file mode 100644 index 00000000..de9c6e38 --- /dev/null +++ b/src/Api/Extensions/StringExtensions.cs @@ -0,0 +1,63 @@ +using System.Text.RegularExpressions; + +namespace Void.Proxy.Api.Extensions; + +public static partial class StringExtensions +{ + private static readonly char[] DefaultDelimiters = [',', ';', '\n']; + + /// + /// Splits a string by multiple delimiters with optional escape character support. + /// + /// The string to split. + /// Custom delimiters to use. If null, uses default delimiters: comma, semicolon, and newline. + /// Optional escape character (e.g., '\') to allow escaped delimiters in the input. + /// Whether to remove empty entries from the result. Defaults to true. + /// An array of strings split by the delimiters. + public static string[] SplitByDelimiters(this string input, char[]? delimiters = null, char? escapeCharacter = null, bool removeEmptyEntries = true) + { + if (string.IsNullOrWhiteSpace(input)) + return []; + + delimiters ??= DefaultDelimiters; + + if (escapeCharacter is not null) + { + return SplitByDelimitersWithEscape(input, delimiters, escapeCharacter.Value, removeEmptyEntries); + } + + var options = removeEmptyEntries ? StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries : StringSplitOptions.TrimEntries; + return input.Split(delimiters, options); + } + + private static string[] SplitByDelimitersWithEscape(string input, char[] delimiters, char escapeCharacter, bool removeEmptyEntries) + { + var pattern = BuildEscapedDelimiterPattern(delimiters, escapeCharacter); + var regex = new Regex(pattern); + var parts = regex.Split(input); + + var result = parts.Select(part => UnescapeDelimiters(part, delimiters, escapeCharacter).Trim()).ToArray(); + + if (removeEmptyEntries) + result = result.Where(part => !string.IsNullOrWhiteSpace(part)).ToArray(); + + return result; + } + + private static string BuildEscapedDelimiterPattern(char[] delimiters, char escapeCharacter) + { + var escapedChar = Regex.Escape(escapeCharacter.ToString()); + var delimiterPattern = string.Join("|", delimiters.Select(d => Regex.Escape(d.ToString()))); + return $"(? logger, IRunOptions runOptions, IConsoleService console, HttpClient httpClient) : INuGetDependencyResolver, IEventListener +public class NuGetDependencyResolver(ILogger logger, IRunOptions runOptions, IConsoleService console, HttpClient httpClient) : INuGetDependencyResolver, IEventListener { private static readonly Option RepositoryOption = new("--repository", "-r") { @@ -42,7 +43,7 @@ public partial class NuGetDependencyResolver(ILogger lo private readonly NuGet.Common.ILogger _nugetLogger = console.GetOptionValue(EnableNugetLoggingOption) ? new NuGetLogger(logger) : NullLogger.Instance; private readonly HashSet _repositories = []; - private IEnumerable UriRepositories => UnescapedSemicolonRegex().Split(Environment.GetEnvironmentVariable("VOID_NUGET_REPOSITORIES") ?? "").Select(repo => repo.Replace(@"\;", ";")).Concat(_repositories.Concat(console.GetOptionValue(RepositoryOption) ?? [])).Where(uri => !string.IsNullOrWhiteSpace(uri)); + private IEnumerable UriRepositories => (Environment.GetEnvironmentVariable("VOID_NUGET_REPOSITORIES") ?? "").SplitByDelimiters([';'], escapeCharacter: '\\').Concat(_repositories.Concat(console.GetOptionValue(RepositoryOption) ?? [])).Where(uri => !string.IsNullOrWhiteSpace(uri)); private IEnumerable Repositories { get @@ -543,7 +544,4 @@ private async Task ProbeRepositoriesAsync(CancellationToken cancellationToken = foreach (var (url, status) in statuses) logger.LogInformation(" - {Url} [{Status}]", url, status); } - - [GeneratedRegex(@"(? Date: Wed, 11 Feb 2026 00:22:54 +0000 Subject: [PATCH 3/3] =?UTF-8?q?refactor(api):=20=F0=9F=94=A5=20addressed?= =?UTF-8?q?=20code=20review=20feedback?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Removed unused System.Text.RegularExpressions import from NuGetDependencyResolver - Added RegexOptions.Compiled for better performance in StringExtensions Co-authored-by: caunt <5324218+caunt@users.noreply.github.com> --- src/Api/Extensions/StringExtensions.cs | 2 +- .../Plugins/Dependencies/Nuget/NuGetDependencyResolver.cs | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/Api/Extensions/StringExtensions.cs b/src/Api/Extensions/StringExtensions.cs index de9c6e38..f7c43667 100644 --- a/src/Api/Extensions/StringExtensions.cs +++ b/src/Api/Extensions/StringExtensions.cs @@ -33,7 +33,7 @@ public static string[] SplitByDelimiters(this string input, char[]? delimiters = private static string[] SplitByDelimitersWithEscape(string input, char[] delimiters, char escapeCharacter, bool removeEmptyEntries) { var pattern = BuildEscapedDelimiterPattern(delimiters, escapeCharacter); - var regex = new Regex(pattern); + var regex = new Regex(pattern, RegexOptions.Compiled); var parts = regex.Split(input); var result = parts.Select(part => UnescapeDelimiters(part, delimiters, escapeCharacter).Trim()).ToArray(); diff --git a/src/Platform/Plugins/Dependencies/Nuget/NuGetDependencyResolver.cs b/src/Platform/Plugins/Dependencies/Nuget/NuGetDependencyResolver.cs index 7e37cc44..5cc1be04 100644 --- a/src/Platform/Plugins/Dependencies/Nuget/NuGetDependencyResolver.cs +++ b/src/Platform/Plugins/Dependencies/Nuget/NuGetDependencyResolver.cs @@ -2,7 +2,6 @@ using System.Reflection; using System.Runtime.Loader; using System.Runtime.Versioning; -using System.Text.RegularExpressions; using Nito.Disposables.Internals; using NuGet.Common; using NuGet.Configuration;