diff --git a/StabilityMatrix.Core/Processes/ProcessRunner.cs b/StabilityMatrix.Core/Processes/ProcessRunner.cs index e830a0e24..665e91fc6 100644 --- a/StabilityMatrix.Core/Processes/ProcessRunner.cs +++ b/StabilityMatrix.Core/Processes/ProcessRunner.cs @@ -651,8 +651,15 @@ public static Task RunBashCommand( /// public static string Quote(string argument) { - var inner = argument.Trim('"'); - return inner.Contains(' ') ? $"\"{inner}\"" : argument; + var inner = argument.Length >= 2 && argument.StartsWith('"') && argument.EndsWith('"') + ? argument[1..^1] + : argument; + + if (!inner.Contains(' ') && !inner.Contains('"')) + return argument; + + var escaped = inner.Replace("\"", "\\\""); + return $"\"{escaped}\""; } /// diff --git a/StabilityMatrix.Core/Python/PipInstallArgs.cs b/StabilityMatrix.Core/Python/PipInstallArgs.cs index 420410166..6c58430d1 100644 --- a/StabilityMatrix.Core/Python/PipInstallArgs.cs +++ b/StabilityMatrix.Core/Python/PipInstallArgs.cs @@ -54,7 +54,15 @@ public PipInstallArgs WithParsedFromRequirementsTxt( requirementsEntries = requirementsEntries.Where(s => !excludeRegex.IsMatch(s)); } - return this.AddArgs(requirementsEntries.Select(Argument.Quoted).ToArray()); + return this.AddArgs(requirementsEntries.Select(ToRequirementArgument).ToArray()); + } + + private static Argument ToRequirementArgument(string requirementEntry) + { + if (requirementEntry.StartsWith('-')) + return Argument.Quoted(requirementEntry); + + return new Argument(requirementEntry); } /// diff --git a/StabilityMatrix.Tests/Core/PipInstallArgsTests.cs b/StabilityMatrix.Tests/Core/PipInstallArgsTests.cs index 29a956aa9..cc7244cb1 100644 --- a/StabilityMatrix.Tests/Core/PipInstallArgsTests.cs +++ b/StabilityMatrix.Tests/Core/PipInstallArgsTests.cs @@ -81,6 +81,26 @@ public void TestParsedFromRequirementsTxt() Assert.AreEqual("torch~=2.0.0 torchvision --extra-index-url https://example.org", args.ToString()); } + [TestMethod] + public void TestParsedFromRequirementsTxt_KeepsEnvironmentMarkerRequirementAsSingleArgument() + { + const string requirements = """ + onnxruntime-gpu==1.22.0; python_version < "3.11" + """; + + var args = new PipInstallArgs().WithParsedFromRequirementsTxt(requirements).ToProcessArgs(); + + Assert.AreEqual(1, args.Count()); + Assert.AreEqual( + "\"onnxruntime-gpu==1.22.0; python_version < \\\"3.11\\\"\"", + args.Single().GetQuotedValue() + ); + Assert.AreEqual( + "\"onnxruntime-gpu==1.22.0; python_version < \\\"3.11\\\"\"", + args.ToString() + ); + } + [TestMethod] public void TestWithUserOverrides() {