Skip to content

Commit fe0f0a3

Browse files
committed
Order Homebrew GitHub CLI versions semantically (#5184)
1 parent 69dfbe0 commit fe0f0a3

2 files changed

Lines changed: 41 additions & 9 deletions

File tree

src/CodeIndex/Cli/GitHubCliExecutableResolver.cs

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -170,8 +170,13 @@ private static IEnumerable<string> EnumerateHomebrewCellarCandidatePaths(string
170170
{
171171
versionDirectories = Directory
172172
.EnumerateDirectories(formulaDirectory)
173+
.Select(CreateHomebrewCellarVersionCandidate)
174+
.OrderByDescending(static candidate => candidate.Parsed)
175+
.ThenByDescending(static candidate => candidate.Version)
176+
.ThenByDescending(static candidate => candidate.Revision)
177+
.ThenByDescending(static candidate => candidate.Path, StringComparer.Ordinal)
173178
.Take(MaxHomebrewCellarVersions)
174-
.OrderByDescending(static path => path, StringComparer.Ordinal)
179+
.Select(static candidate => candidate.Path)
175180
.ToArray();
176181
}
177182
catch (Exception ex) when (ex is IOException
@@ -187,6 +192,24 @@ or NotSupportedException
187192
yield return Path.Combine(versionDirectory, "bin", "gh");
188193
}
189194

195+
private static HomebrewCellarVersionCandidate CreateHomebrewCellarVersionCandidate(string path)
196+
{
197+
var directoryName = Path.GetFileName(path);
198+
var versionText = directoryName;
199+
var revision = 0;
200+
var revisionSeparator = directoryName.LastIndexOf('_');
201+
if (revisionSeparator >= 0)
202+
{
203+
versionText = directoryName[..revisionSeparator];
204+
if (!int.TryParse(directoryName[(revisionSeparator + 1)..], out revision) || revision < 0)
205+
return new HomebrewCellarVersionCandidate(path, new Version(0, 0), 0, Parsed: false);
206+
}
207+
208+
return Version.TryParse(versionText, out var version)
209+
? new HomebrewCellarVersionCandidate(path, version, revision, Parsed: true)
210+
: new HomebrewCellarVersionCandidate(path, new Version(0, 0), 0, Parsed: false);
211+
}
212+
190213
private static bool IsMacHomebrewCellarGhPath(string path)
191214
{
192215
if (!OperatingSystem.IsMacOS() || !Path.IsPathFullyQualified(path))
@@ -249,4 +272,10 @@ private static bool ProbeVersion(string executablePath, CancellationToken cancel
249272
}
250273

251274
private sealed record GitHubCliExecutableResolution(string? Path, GitExecutableStatus Status);
275+
276+
private sealed record HomebrewCellarVersionCandidate(
277+
string Path,
278+
Version Version,
279+
int Revision,
280+
bool Parsed);
252281
}

tests/CodeIndex.Tests/GitHubCliExecutableResolverTests.cs

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -24,21 +24,24 @@ public void KnownCandidates_AreAbsoluteExpectedNamesAndNeverUseCurrentDirectory_
2424
}
2525

2626
[Fact]
27-
public void HomebrewCellarCandidates_EnumerateVersionedRegularTargetsWithoutLaunchingBinSymlinks_Issue5184()
27+
public void HomebrewCellarCandidates_OrderSemanticallyBeforeCappingWithoutLaunchingBinSymlinks_Issue5184()
2828
{
2929
var prefix = TestProjectHelper.CreateTempProject("cdidx_gh_homebrew_5184");
3030
try
3131
{
32-
var older = Path.Combine(prefix, "Cellar", "gh", "2.94.0", "bin", "gh");
33-
var newer = Path.Combine(prefix, "Cellar", "gh", "2.95.0", "bin", "gh");
34-
Directory.CreateDirectory(Path.GetDirectoryName(older)!);
35-
Directory.CreateDirectory(Path.GetDirectoryName(newer)!);
36-
File.WriteAllText(older, "older");
37-
File.WriteAllText(newer, "newer");
32+
var expected = Enumerable.Range(9, 32)
33+
.Reverse()
34+
.Select(minor => Path.Combine(prefix, "Cellar", "gh", $"2.{minor}.0", "bin", "gh"))
35+
.ToArray();
36+
foreach (var minor in Enumerable.Range(1, 40))
37+
{
38+
Directory.CreateDirectory(
39+
Path.Combine(prefix, "Cellar", "gh", $"2.{minor}.0", "bin"));
40+
}
3841

3942
var candidates = GitHubCliExecutableResolver.HomebrewCellarCandidatePathsForTests(prefix);
4043

41-
Assert.Equal([newer, older], candidates);
44+
Assert.Equal(expected, candidates);
4245
Assert.All(candidates, candidate =>
4346
{
4447
Assert.True(Path.IsPathFullyQualified(candidate));

0 commit comments

Comments
 (0)