Skip to content

Commit

Permalink
Allow using .git directory instead of gitdir redirect in submodules. (#…
Browse files Browse the repository at this point in the history
…653)

* Allow using .git directory instead of gitdir redirect in submodules.

* Address review comments and add test for old-style submodule behavior.

* Use .git dir as the common directory as well.

* Add more details to the comments about how this case can happen.

* Address code review comments.

* Allow empty dir

Co-authored-by: tmat <tomas.matousek@microsoft.com>
  • Loading branch information
crummel and tmat committed Aug 12, 2021
1 parent 9006950 commit 5e2c4f1
Show file tree
Hide file tree
Showing 2 changed files with 28 additions and 3 deletions.
23 changes: 21 additions & 2 deletions src/Microsoft.Build.Tasks.Git.UnitTests/GitRepositoryTests.cs
Expand Up @@ -297,6 +297,7 @@ public void Submodules_Errors()
{
"S10: 'sub10' 'http://github.com'",
"S11: 'sub11' 'http://github.com'",
"S6: 'sub6' 'http://github.com'",
"S9: 'sub9' 'http://github.com'"
}, submodules.Select(s => $"{s.Name}: '{s.WorkingDirectoryRelativePath}' '{s.Url}'"));

Expand All @@ -313,8 +314,6 @@ public void Submodules_Errors()
TestUtilities.GetExceptionMessage(() => File.ReadAllText(Path.Combine(workingDir.Path, "sub4", ".git"))),
// Could not find a part of the path 'sub5\.git'.
TestUtilities.GetExceptionMessage(() => File.ReadAllText(Path.Combine(workingDir.Path, "sub5", ".git"))),
// Access to the path 'sub6\.git' is denied
TestUtilities.GetExceptionMessage(() => File.ReadAllText(Path.Combine(workingDir.Path, "sub6", ".git"))),
// The format of the file 'sub7\.git' is invalid.
string.Format(Resources.FormatOfFileIsInvalid, Path.Combine(workingDir.Path, "sub7", ".git")),
// Path specified in file 'sub8\.git' is invalid.
Expand Down Expand Up @@ -358,5 +357,25 @@ public void GetSubmoduleHeadCommitSha()
var repository = new GitRepository(GitEnvironment.Empty, GitConfig.Empty, gitDir.Path, gitDir.Path, workingDir.Path);
Assert.Equal("0000000000000000000000000000000000000000", repository.ReadSubmoduleHeadCommitSha(submoduleWorkingDir.Path));
}

[Fact]
public void GetOldStyleSubmoduleHeadCommitSha()
{
using var temp = new TempRoot();

var gitDir = temp.CreateDirectory();
var workingDir = temp.CreateDirectory();

// this is a unusual but legal case which can occur with older versions of Git or other tools.
// see https://git-scm.com/docs/gitsubmodules#_forms for more details.
var oldStyleSubmoduleWorkingDir = workingDir.CreateDirectory("old-style-submodule");
var oldStyleSubmoduleGitDir = oldStyleSubmoduleWorkingDir.CreateDirectory(".git");
var oldStyleSubmoduleRefsHeadDir = oldStyleSubmoduleGitDir.CreateDirectory("refs").CreateDirectory("heads");
oldStyleSubmoduleRefsHeadDir.CreateFile("branch1").WriteAllText("1111111111111111111111111111111111111111");
oldStyleSubmoduleGitDir.CreateFile("HEAD").WriteAllText("ref: refs/heads/branch1");

var repository = new GitRepository(GitEnvironment.Empty, GitConfig.Empty, gitDir.Path, gitDir.Path, workingDir.Path);
Assert.Equal("1111111111111111111111111111111111111111", repository.ReadSubmoduleHeadCommitSha(oldStyleSubmoduleWorkingDir.Path));
}
}
}
8 changes: 7 additions & 1 deletion src/Microsoft.Build.Tasks.Git/GitDataReader/GitRepository.cs
Expand Up @@ -211,7 +211,13 @@ public static GitRepository OpenRepository(GitRepositoryLocation location, GitEn
/// <returns>Null if the HEAD tip reference can't be resolved.</returns>
internal string? ReadSubmoduleHeadCommitSha(string submoduleWorkingDirectoryFullPath)
{
var gitDirectory = ReadDotGitFile(Path.Combine(submoduleWorkingDirectoryFullPath, GitDirName));
// Submodules don't usually have their own .git directories but this is still legal.
// This can occur with older versions of Git or other tools, or when a user clones one
// repo into another's source tree (but it was not yet registered as a submodule).
// See https://git-scm.com/docs/gitsubmodules#_forms for more details.
var dotGitPath = Path.Combine(submoduleWorkingDirectoryFullPath, GitDirName);

var gitDirectory = Directory.Exists(dotGitPath) ? dotGitPath : ReadDotGitFile(dotGitPath);
if (!IsGitDirectory(gitDirectory, out var commonDirectory))
{
return null;
Expand Down

0 comments on commit 5e2c4f1

Please sign in to comment.