|
6 | 6 | using System.Globalization;
|
7 | 7 | using System.IO;
|
8 | 8 | using System.Linq;
|
| 9 | +using System.Runtime.InteropServices; |
9 | 10 | using System.Text;
|
10 | 11 |
|
11 | 12 | namespace Nerdbank.GitVersioning.ManagedGit
|
@@ -110,16 +111,14 @@ public GitRepository(string workingDirectory, string gitDirectory, string common
|
110 | 111 | var length = alternateStream!.Read(alternates);
|
111 | 112 | alternates = alternates.Slice(0, length);
|
112 | 113 |
|
113 |
| - int index = 0; |
114 |
| - |
115 |
| - while ((index = alternates.IndexOf((byte)':')) > 0) |
| 114 | + foreach (var alternate in ParseAlternates(alternates)) |
116 | 115 | {
|
117 |
| - var alternate = GetString(alternates.Slice(0, index)); |
118 |
| - alternate = Path.GetFullPath(Path.Combine(this.ObjectDirectory, alternate)); |
119 |
| - |
120 |
| - this.alternates.Add(GitRepository.Create(workingDirectory, gitDirectory, commonDirectory, alternate)); |
121 |
| - |
122 |
| - alternates = alternates.Slice(index + 1); |
| 116 | + this.alternates.Add( |
| 117 | + GitRepository.Create( |
| 118 | + workingDirectory, |
| 119 | + gitDirectory, |
| 120 | + commonDirectory, |
| 121 | + objectDirectory: Path.GetFullPath(Path.Combine(this.ObjectDirectory, alternate)))); |
123 | 122 | }
|
124 | 123 | }
|
125 | 124 |
|
@@ -722,5 +721,47 @@ public static unsafe string GetString(ReadOnlySpan<byte> bytes)
|
722 | 721 | return Encoding.GetString(pBytes, bytes.Length);
|
723 | 722 | }
|
724 | 723 | }
|
| 724 | + |
| 725 | + /// <summary> |
| 726 | + /// Parses the contents of the alternates file, and returns a list of (relative) paths to the alternate object directories. |
| 727 | + /// </summary> |
| 728 | + /// <param name="alternates"> |
| 729 | + /// The contents of the alternates files. |
| 730 | + /// </param> |
| 731 | + /// <returns> |
| 732 | + /// A list of (relative) paths to the alternate object directories. |
| 733 | + /// </returns> |
| 734 | + public static List<string> ParseAlternates(ReadOnlySpan<byte> alternates) |
| 735 | + => ParseAlternates(alternates, RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? 2 : 0); |
| 736 | + |
| 737 | + /// <summary> |
| 738 | + /// Parses the contents of the alternates file, and returns a list of (relative) paths to the alternate object directories. |
| 739 | + /// </summary> |
| 740 | + /// <param name="alternates"> |
| 741 | + /// The contents of the alternates files. |
| 742 | + /// </param> |
| 743 | + /// <param name="skipCount"> |
| 744 | + /// The number of bytes to skip in the span when looking for a delimiter. |
| 745 | + /// </param> |
| 746 | + /// <returns> |
| 747 | + /// A list of (relative) paths to the alternate object directories. |
| 748 | + /// </returns> |
| 749 | + public static List<string> ParseAlternates(ReadOnlySpan<byte> alternates, int skipCount) |
| 750 | + { |
| 751 | + List<string> values = new List<string>(); |
| 752 | + |
| 753 | + int index; |
| 754 | + |
| 755 | + // The alternates path is colon (:)-separated. On Windows, there may be full paths, such as |
| 756 | + // C:/Users/username/source/repos/nbgv/.git, which also contain a colon. Because the colon |
| 757 | + // can only appear at the second position, we skip the first two characters (e.g. C:) on Windows. |
| 758 | + while (alternates.Length > skipCount && (index = alternates.Slice(skipCount).IndexOfAny((byte)':', (byte)'\n')) > 0) |
| 759 | + { |
| 760 | + values.Add(GetString(alternates.Slice(0, skipCount + index))); |
| 761 | + alternates = alternates.Slice(skipCount + index + 1); |
| 762 | + } |
| 763 | + |
| 764 | + return values; |
| 765 | + } |
725 | 766 | }
|
726 | 767 | }
|
0 commit comments