Skip to content

Commit c311a3f

Browse files
committed
Add unit tests for alternates with colons in their path (e.g. C:/Users/)
1 parent cb37baa commit c311a3f

File tree

2 files changed

+30
-4
lines changed

2 files changed

+30
-4
lines changed

src/NerdBank.GitVersioning.Tests/ManagedGit/GitRepositoryTests.cs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -305,6 +305,19 @@ public void ParseAlternates_TwoValues_Test()
305305
a => Assert.Equal("../../clone/.git/objects", a));
306306
}
307307

308+
[Fact]
309+
public void ParseAlternates_PathWithColon_Test()
310+
{
311+
var alternates = GitRepository.ParseAlternates(
312+
Encoding.UTF8.GetBytes("C:/Users/nbgv/objects:C:/Users/nbgv2/objects/:../../clone/.git/objects\n"),
313+
2);
314+
Assert.Collection(
315+
alternates,
316+
a => Assert.Equal("C:/Users/nbgv/objects", a),
317+
a => Assert.Equal("C:/Users/nbgv2/objects/", a),
318+
a => Assert.Equal("../../clone/.git/objects", a));
319+
}
320+
308321
private static void AssertPath(string expected, string actual)
309322
{
310323
Assert.Equal(

src/NerdBank.GitVersioning/ManagedGit/GitRepository.cs

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ public GitRepository(string workingDirectory, string gitDirectory, string common
111111
var length = alternateStream!.Read(alternates);
112112
alternates = alternates.Slice(0, length);
113113

114-
foreach(var alternate in ParseAlternates(alternates))
114+
foreach (var alternate in ParseAlternates(alternates))
115115
{
116116
this.alternates.Add(
117117
GitRepository.Create(
@@ -724,16 +724,29 @@ public static unsafe string GetString(ReadOnlySpan<byte> bytes)
724724
/// A list of (relative) paths to the alternate object directories.
725725
/// </returns>
726726
public static List<string> ParseAlternates(ReadOnlySpan<byte> alternates)
727+
=> ParseAlternates(alternates, RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? 2 : 0);
728+
729+
/// <summary>
730+
/// Parses the contents of the alternates file, and returns a list of (relative) paths to the alternate object directories.
731+
/// </summary>
732+
/// <param name="alternates">
733+
/// The contents of the alternates files.
734+
/// </param>
735+
/// <param name="skipCount">
736+
/// The number of bytes to skip in the span when looking for a delimiter.
737+
/// </param>
738+
/// <returns>
739+
/// A list of (relative) paths to the alternate object directories.
740+
/// </returns>
741+
public static List<string> ParseAlternates(ReadOnlySpan<byte> alternates, int skipCount)
727742
{
728743
List<string> values = new List<string>();
729744

730-
int index = 0;
745+
int index;
731746

732747
// The alternates path is colon (:)-separated. On Windows, there may be full paths, such as
733748
// C:/Users/username/source/repos/nbgv/.git, which also contain a colon. Because the colon
734749
// can only appear at the second position, we skip the first two characters (e.g. C:) on Windows.
735-
int skipCount = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? 2 : 0;
736-
737750
while (alternates.Length > skipCount && (index = alternates.Slice(skipCount).IndexOfAny((byte)':', (byte)'\n')) > 0)
738751
{
739752
values.Add(GetString(alternates.Slice(0, skipCount + index)));

0 commit comments

Comments
 (0)