Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 21 additions & 3 deletions src/Elastic.Documentation.Configuration/FileSystemFactory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -174,10 +174,28 @@ public static ScopedFileSystem ScopeSourceDirectoryForWrite(IFileSystem inner, s
/// </summary>
public static ScopedFileSystem RealGitRootForPath(string? path)
{
if (path is null)
var root = path is null ? Paths.WorkingDirectoryRoot.FullName : Paths.FindGitRoot(path);
var roots = new List<string> { root, Paths.ApplicationData.FullName };

// In a git worktree the local .git entry is a file pointing to the main repo's
// .git/worktrees/<name> directory. GitCheckoutInformation needs to read config and
// HEAD from the main repo's .git dir, which lives outside the worktree root.
// Add it as an explicit scope root so those reads are not rejected.
var worktreePointer = Path.Join(root, ".git");
if (File.Exists(worktreePointer))
{
var gitdir = File.ReadAllText(worktreePointer).Replace("gitdir:", "").Trim();
// gitdir = /main/repo/.git/worktrees/<name> — go up two levels to reach .git
var mainGitDir = Path.GetFullPath(Path.Join(gitdir, "..", ".."));
if (Directory.Exists(mainGitDir))
roots.Add(mainGitDir);
}

// Fast path: no worktree detected and path was null — reuse the pre-built instance
if (roots.Count == 2 && path is null)
return RealRead;
var root = Paths.FindGitRoot(path);
return new ScopedFileSystem(new FileSystem(), new ScopedFileSystemOptions([root, Paths.ApplicationData.FullName])

return new ScopedFileSystem(new FileSystem(), new ScopedFileSystemOptions([.. roots])
{
AllowedHiddenFolderNames = new HashSet<string>(StringComparer.OrdinalIgnoreCase) { ".git", ".artifacts" },
AllowedHiddenFileNames = new HashSet<string>(StringComparer.OrdinalIgnoreCase) { ".git", ".doc.state" }
Expand Down
Loading