Skip to content

Commit 62454d9

Browse files
Use common dir to locate packed-refs and reftable (#1665)
Co-authored-by: Tomas Matousek <tomat@microsoft.com>
1 parent 067d8ae commit 62454d9

3 files changed

Lines changed: 58 additions & 11 deletions

File tree

src/Microsoft.Build.Tasks.Git.UnitTests/GitReferenceResolverTests.cs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -106,13 +106,13 @@ public void ResolveReference_Packed()
106106
using var temp = new TempRoot();
107107

108108
var gitDir = temp.CreateDirectory();
109+
var commonDir = temp.CreateDirectory();
109110

110-
gitDir.CreateFile("packed-refs").WriteAllText(
111+
commonDir.CreateFile("packed-refs").WriteAllText(
111112
@"# pack-refs with: peeled fully-peeled sorted
112113
1111111111111111111111111111111111111111 refs/heads/master
113114
2222222222222222222222222222222222222222 refs/heads/br2
114115
");
115-
var commonDir = temp.CreateDirectory();
116116
var refsHeadsDir = commonDir.CreateDirectory("refs").CreateDirectory("heads");
117117

118118
refsHeadsDir.CreateFile("br1").WriteAllText("ref: refs/heads/br2");
@@ -130,14 +130,14 @@ public void ResolveReference_Packed_SHA256()
130130
using var temp = new TempRoot();
131131

132132
var gitDir = temp.CreateDirectory();
133+
var commonDir = temp.CreateDirectory();
133134

134135
// Packed refs with SHA256 hashes (64 characters)
135-
gitDir.CreateFile("packed-refs").WriteAllText(
136+
commonDir.CreateFile("packed-refs").WriteAllText(
136137
@"# pack-refs with: peeled fully-peeled sorted
137138
1111111111111111111111111111111111111111111111111111111111111111 refs/heads/master
138139
2222222222222222222222222222222222222222222222222222222222222222 refs/heads/br2
139140
");
140-
var commonDir = temp.CreateDirectory();
141141
var refsHeadsDir = commonDir.CreateDirectory("refs").CreateDirectory("heads");
142142

143143
refsHeadsDir.CreateFile("br1").WriteAllText("ref: refs/heads/br2");
@@ -230,7 +230,7 @@ public void ResolveReference_RefTable()
230230
var gitDir = temp.CreateDirectory();
231231
var commonDir = temp.CreateDirectory();
232232

233-
var refTableDir = gitDir.CreateDirectory("reftable");
233+
var refTableDir = commonDir.CreateDirectory("reftable");
234234

235235
refTableDir.CreateFile("tables.list").WriteAllText("""
236236
2.ref

src/Microsoft.Build.Tasks.Git.UnitTests/GitRepositoryTests.cs

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,46 @@ public void TryFindRepository_Worktree_Realistic()
130130
Assert.Null(repository.WorkingDirectory);
131131
}
132132

133+
[Fact]
134+
public void Worktree_Packed_GetHeadCommitSha()
135+
{
136+
using var temp = new TempRoot();
137+
138+
var mainWorkingDir = temp.CreateDirectory();
139+
var mainWorkingSubDir = mainWorkingDir.CreateDirectory("A");
140+
var mainGitDir = mainWorkingDir.CreateDirectory(".git");
141+
mainGitDir.CreateFile("HEAD");
142+
mainGitDir.CreateFile("packed-refs").WriteAllText(
143+
@"# pack-refs with: peeled fully-peeled sorted
144+
1111111111111111111111111111111111111111 refs/heads/master
145+
2222222222222222222222222222222222222222 refs/heads/br2
146+
");
147+
148+
var worktreesDir = mainGitDir.CreateDirectory("worktrees");
149+
var worktreeGitDir = worktreesDir.CreateDirectory("C");
150+
var worktreeGitSubDir = worktreeGitDir.CreateDirectory("B");
151+
var worktreeDir = temp.CreateDirectory();
152+
var worktreeSubDir = worktreeDir.CreateDirectory("C");
153+
var worktreeGitFile = worktreeDir.CreateFile(".git").WriteAllText("gitdir: " + worktreeGitDir + " \r\n\t\v");
154+
155+
worktreeGitDir.CreateFile("HEAD").WriteAllText("ref: refs/heads/br2\n");
156+
worktreeGitDir.CreateFile("commondir").WriteAllText("../..\n");
157+
worktreeGitDir.CreateFile("gitdir").WriteAllText(worktreeGitFile.Path + " \r\n\t\v");
158+
159+
// start under worktree directory:
160+
Assert.True(GitRepository.TryFindRepository(worktreeSubDir.Path, out var location));
161+
Assert.Equal(worktreeGitDir.Path, location.GitDirectory);
162+
Assert.Equal(mainGitDir.Path, location.CommonDirectory);
163+
Assert.Equal(worktreeDir.Path, location.WorkingDirectory);
164+
165+
var repository = GitRepository.OpenRepository(location, GitEnvironment.Empty);
166+
Assert.Equal(location.GitDirectory, repository.GitDirectory);
167+
Assert.Equal(location.WorkingDirectory, repository.WorkingDirectory);
168+
Assert.Equal(location.CommonDirectory, repository.CommonDirectory);
169+
170+
Assert.Equal("2222222222222222222222222222222222222222", repository.GetHeadCommitSha());
171+
}
172+
133173
[Fact]
134174
public void LocateRepository_Submodule()
135175
{

src/Microsoft.Build.Tasks.Git/GitDataReader/GitReferenceResolver.cs

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -42,8 +42,8 @@ public GitReferenceResolver(string gitDirectory, string commonDirectory, Referen
4242
_commonDirectory = commonDirectory;
4343
_storageFormat = storageFormat;
4444
_objectNameFormat = objectNameFormat;
45-
_lazyPackedReferences = new(() => ReadPackedReferences(_gitDirectory));
46-
_lazyRefTableReferenceReaders = new(() => CreateRefTableReaders(_gitDirectory, _openedRefTableReaders));
45+
_lazyPackedReferences = new(() => ReadPackedReferences(_commonDirectory));
46+
_lazyRefTableReferenceReaders = new(() => CreateRefTableReaders(_commonDirectory, _openedRefTableReaders));
4747
}
4848

4949
public void Dispose()
@@ -59,11 +59,15 @@ public void Dispose()
5959
}
6060
}
6161

62-
private ImmutableDictionary<string, string> ReadPackedReferences(string gitDirectory)
62+
private ImmutableDictionary<string, string> ReadPackedReferences(string commonDirectory)
6363
{
6464
// https://git-scm.com/docs/git-pack-refs
6565

66-
var packedRefsPath = Path.Combine(gitDirectory, PackedRefsFileName);
66+
// Although the above doc specifies 'packaged-refs' file is in GIT_DIR,
67+
// it is actually in the common directory as specified in
68+
// https://git-scm.com/docs/gitrepository-layout#Documentation/gitrepository-layout.txt-packed-refs
69+
70+
var packedRefsPath = Path.Combine(commonDirectory, PackedRefsFileName);
6771
if (!File.Exists(packedRefsPath))
6872
{
6973
return ImmutableDictionary<string, string>.Empty;
@@ -174,9 +178,12 @@ internal ImmutableDictionary<string, string> ReadPackedReferences(TextReader rea
174178

175179
/// <exception cref="IOException"/>
176180
/// <exception cref="InvalidDataException"/>
177-
private static IEnumerable<GitRefTableReader> CreateRefTableReaders(string gitDirectory, List<GitRefTableReader> openReaders)
181+
private static IEnumerable<GitRefTableReader> CreateRefTableReaders(string commonDirectory, List<GitRefTableReader> openReaders)
178182
{
179-
var refTableDirectory = Path.Combine(gitDirectory, RefTableDirectoryName);
183+
// Although https://git-scm.com/docs/reftable#_layout specifies reftable to be in GIT_DIR,
184+
// it is actually in the common directory. This is currently not documented.
185+
186+
var refTableDirectory = Path.Combine(commonDirectory, RefTableDirectoryName);
180187
var tablesFilePath = Path.Combine(refTableDirectory, TablesListFileName);
181188

182189
// Create lazily-evaluated sequence of readers for each entry in the tables.list file (in reverse order).

0 commit comments

Comments
 (0)