mirror of
https://github.com/davidkaya/aryx.git
synced 2026-08-03 18:38:35 +02:00
fix: make copilot CLI path resolution cross-platform
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
@@ -8,6 +8,10 @@ internal static class CopilotCliPathResolver
|
||||
private const string CopilotCommandName = "copilot";
|
||||
private const string DefaultWindowsCommandProcessor = "cmd.exe";
|
||||
private const string DefaultWindowsPathExtensions = ".COM;.EXE;.BAT;.CMD";
|
||||
private const char WindowsSearchPathSeparator = ';';
|
||||
private const char UnixSearchPathSeparator = ':';
|
||||
private const char WindowsDirectorySeparator = '\\';
|
||||
private const char UnixDirectorySeparator = '/';
|
||||
|
||||
private static readonly string[] BlockedCliEnvironmentPrefixes = ["BUN_", "COPILOT_", "ELECTRON_", "NODE_", "NPM_"];
|
||||
|
||||
@@ -125,7 +129,7 @@ internal static class CopilotCliPathResolver
|
||||
{
|
||||
foreach (string candidateName in GetCandidateFileNames(pathExtValue, isWindows))
|
||||
{
|
||||
string candidatePath = Path.Combine(directory, candidateName);
|
||||
string candidatePath = CombineSearchPath(directory, candidateName, isWindows);
|
||||
if (fileExists(candidatePath))
|
||||
{
|
||||
return candidatePath;
|
||||
@@ -145,7 +149,7 @@ internal static class CopilotCliPathResolver
|
||||
|
||||
StringComparer comparer = isWindows ? StringComparer.OrdinalIgnoreCase : StringComparer.Ordinal;
|
||||
foreach (string directory in pathValue
|
||||
.Split(Path.PathSeparator, StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries)
|
||||
.Split(GetSearchPathSeparator(isWindows), StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries)
|
||||
.Select(segment => segment.Trim('"'))
|
||||
.Where(segment => !string.IsNullOrWhiteSpace(segment))
|
||||
.Distinct(comparer))
|
||||
@@ -184,6 +188,38 @@ internal static class CopilotCliPathResolver
|
||||
}
|
||||
}
|
||||
|
||||
private static char GetSearchPathSeparator(bool isWindows)
|
||||
{
|
||||
return isWindows ? WindowsSearchPathSeparator : UnixSearchPathSeparator;
|
||||
}
|
||||
|
||||
private static string CombineSearchPath(string directory, string fileName, bool isWindows)
|
||||
{
|
||||
if (string.IsNullOrEmpty(directory))
|
||||
{
|
||||
return fileName;
|
||||
}
|
||||
|
||||
if (EndsWithDirectorySeparator(directory, isWindows))
|
||||
{
|
||||
return directory + fileName;
|
||||
}
|
||||
|
||||
return directory + GetDirectorySeparator(isWindows) + fileName;
|
||||
}
|
||||
|
||||
private static bool EndsWithDirectorySeparator(string path, bool isWindows)
|
||||
{
|
||||
char lastCharacter = path[^1];
|
||||
return lastCharacter == GetDirectorySeparator(isWindows)
|
||||
|| (isWindows && lastCharacter == UnixDirectorySeparator);
|
||||
}
|
||||
|
||||
private static char GetDirectorySeparator(bool isWindows)
|
||||
{
|
||||
return isWindows ? WindowsDirectorySeparator : UnixDirectorySeparator;
|
||||
}
|
||||
|
||||
private static IEnumerable<KeyValuePair<string, string?>> GetCurrentEnvironmentVariables()
|
||||
{
|
||||
return Environment.GetEnvironmentVariables()
|
||||
|
||||
@@ -8,9 +8,10 @@ public sealed class CopilotCliPathResolverTests
|
||||
public void Resolve_UsesCopilotFromPath()
|
||||
{
|
||||
string copilotDirectory = @"C:\tools\copilot";
|
||||
string expectedCliPath = @"C:\tools\copilot\copilot.exe";
|
||||
HashSet<string> existingFiles = new(StringComparer.OrdinalIgnoreCase)
|
||||
{
|
||||
Path.Combine(copilotDirectory, "copilot.exe"),
|
||||
expectedCliPath,
|
||||
};
|
||||
|
||||
string? cliPath = CopilotCliPathResolver.Resolve(
|
||||
@@ -19,16 +20,17 @@ public sealed class CopilotCliPathResolverTests
|
||||
isWindows: true,
|
||||
fileExists: existingFiles.Contains);
|
||||
|
||||
Assert.Equal(Path.Combine(copilotDirectory, "copilot.exe"), cliPath, ignoreCase: true);
|
||||
Assert.Equal(expectedCliPath, cliPath, ignoreCase: true);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Resolve_UsesDefaultWindowsExtensionsWhenPathExtMissing()
|
||||
{
|
||||
string copilotDirectory = @"C:\tools\copilot";
|
||||
string expectedCliPath = @"C:\tools\copilot\copilot.cmd";
|
||||
HashSet<string> existingFiles = new(StringComparer.OrdinalIgnoreCase)
|
||||
{
|
||||
Path.Combine(copilotDirectory, "copilot.cmd"),
|
||||
expectedCliPath,
|
||||
};
|
||||
|
||||
string? cliPath = CopilotCliPathResolver.Resolve(
|
||||
@@ -37,7 +39,25 @@ public sealed class CopilotCliPathResolverTests
|
||||
isWindows: true,
|
||||
fileExists: existingFiles.Contains);
|
||||
|
||||
Assert.Equal(Path.Combine(copilotDirectory, "copilot.cmd"), cliPath, ignoreCase: true);
|
||||
Assert.Equal(expectedCliPath, cliPath, ignoreCase: true);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Resolve_UsesCopilotFromPathOutsideWindows()
|
||||
{
|
||||
const string expectedCliPath = "/usr/local/bin/copilot";
|
||||
HashSet<string> existingFiles = new(StringComparer.Ordinal)
|
||||
{
|
||||
expectedCliPath,
|
||||
};
|
||||
|
||||
string? cliPath = CopilotCliPathResolver.Resolve(
|
||||
pathValue: "/usr/bin:/usr/local/bin",
|
||||
pathExtValue: null,
|
||||
isWindows: false,
|
||||
fileExists: existingFiles.Contains);
|
||||
|
||||
Assert.Equal(expectedCliPath, cliPath);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
||||
Reference in New Issue
Block a user