Skip to content

Commit a420346

Browse files
Mpdreamzclaude
andcommitted
Consolidate git root discovery and remove Paths.GitCommonRoot static
Three changes: 1. FileSystemFactory.FindGitRoot removed — ForPath/ForPathWrite now call Paths.FindGitRoot, which is the single canonical git-root walker. 2. Paths.DetermineSourceDirectoryRoot simplified — the loop body had a dead branch (checked GetDirectories.Length == 0 in the while condition then re-checked inside). Rewritten to a clean while-loop matching FindGitRoot's structure; semantics unchanged. 3. Paths.GitCommonRoot static field and InitGitCommonRoot removed — the static ran complex logic (ScopedFileSystem creation + file read) at class init time and was only used by AssembleContext and CodexContext. Both now call Paths.ResolveGitCommonRoot(readFileSystem, workingRoot) directly, which is already public and takes explicit dependencies. Paths.cs no longer references Nullean.ScopedFileSystem. Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
1 parent a385472 commit a420346

4 files changed

Lines changed: 36 additions & 42 deletions

File tree

src/Elastic.Codex/CodexContext.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,9 @@ public CodexContext(
4646
ReadFileSystem = readFileSystem;
4747
WriteFileSystem = writeFileSystem;
4848

49-
var defaultCheckoutDirectory = Path.Join(Paths.GitCommonRoot.FullName, ".artifacts", "codex", "clone");
49+
var workingRoot = ReadFileSystem.DirectoryInfo.New(Paths.WorkingDirectoryRoot.FullName);
50+
var gitCommonRoot = Paths.ResolveGitCommonRoot(ReadFileSystem, workingRoot);
51+
var defaultCheckoutDirectory = Path.Join(gitCommonRoot.FullName, ".artifacts", "codex", "clone");
5052
CheckoutDirectory = ReadFileSystem.DirectoryInfo.New(checkoutDirectory ?? defaultCheckoutDirectory);
5153

5254
var defaultOutputDirectory = Path.Join(Paths.WorkingDirectoryRoot.FullName, ".artifacts", "codex", "docs");

src/Elastic.Documentation.Configuration/FileSystemFactory.cs

Lines changed: 2 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ public static ScopedFileSystem ForPath(string? path)
107107
{
108108
if (path is null)
109109
return RealRead;
110-
var root = FindGitRoot(path);
110+
var root = Paths.FindGitRoot(path);
111111
return new ScopedFileSystem(new FileSystem(), new ScopedFileSystemOptions([root, Paths.ApplicationData.FullName])
112112
{
113113
AllowedHiddenFolderNames = new HashSet<string>(StringComparer.OrdinalIgnoreCase) { ".git", ".artifacts" },
@@ -126,7 +126,7 @@ public static ScopedFileSystem ForPathWrite(string? path, string? output = null)
126126
if (path is null && output is null)
127127
return RealWrite;
128128

129-
var gitRoot = path is not null ? FindGitRoot(path) : Paths.WorkingDirectoryRoot.FullName;
129+
var gitRoot = path is not null ? Paths.FindGitRoot(path) : Paths.WorkingDirectoryRoot.FullName;
130130
var roots = new List<string> { gitRoot, Paths.ApplicationData.FullName };
131131

132132
if (output is not null)
@@ -143,20 +143,4 @@ public static ScopedFileSystem ForPathWrite(string? path, string? output = null)
143143
});
144144
}
145145

146-
// Walks up from startPath to find the nearest .git directory or file (worktree support).
147-
// Uses System.IO directly — acceptable bootstrap, same pattern as Paths.DetermineWorkingDirectoryRoot.
148-
private static string FindGitRoot(string startPath)
149-
{
150-
var resolved = Path.IsPathRooted(startPath) ? startPath : Path.GetFullPath(startPath);
151-
var dir = Directory.Exists(resolved)
152-
? new DirectoryInfo(resolved)
153-
: new DirectoryInfo(Path.GetDirectoryName(resolved) ?? resolved);
154-
while (dir != null)
155-
{
156-
if (dir.GetDirectories(".git").Length > 0 || dir.GetFiles(".git").Length > 0)
157-
return dir.FullName;
158-
dir = dir.Parent;
159-
}
160-
return Path.GetPathRoot(resolved) ?? resolved;
161-
}
162146
}

src/Elastic.Documentation.Configuration/Paths.cs

Lines changed: 28 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -4,18 +4,35 @@
44

55
using System.Diagnostics.CodeAnalysis;
66
using System.IO.Abstractions;
7-
using Nullean.ScopedFileSystem;
87

98
namespace Elastic.Documentation.Configuration;
109

1110
public static class Paths
1211
{
1312
public static readonly DirectoryInfo WorkingDirectoryRoot = DetermineWorkingDirectoryRoot();
1413

15-
public static readonly DirectoryInfo GitCommonRoot = InitGitCommonRoot();
16-
1714
public static readonly DirectoryInfo ApplicationData = GetApplicationFolder();
1815

16+
/// <summary>
17+
/// Walks up from <paramref name="startPath"/> until a <c>.git</c> directory or file
18+
/// (worktree pointer) is found and returns that ancestor. Returns <paramref name="startPath"/>
19+
/// itself when no git root is found.
20+
/// </summary>
21+
public static string FindGitRoot(string startPath)
22+
{
23+
var resolved = Path.IsPathRooted(startPath) ? startPath : Path.GetFullPath(startPath);
24+
var dir = Directory.Exists(resolved)
25+
? new DirectoryInfo(resolved)
26+
: new DirectoryInfo(Path.GetDirectoryName(resolved) ?? resolved);
27+
while (dir != null)
28+
{
29+
if (dir.GetDirectories(".git").Length > 0 || dir.GetFiles(".git").Length > 0)
30+
return dir.FullName;
31+
dir = dir.Parent;
32+
}
33+
return resolved;
34+
}
35+
1936
private static DirectoryInfo DetermineWorkingDirectoryRoot()
2037
{
2138
var directory = new DirectoryInfo(Directory.GetCurrentDirectory());
@@ -33,22 +50,23 @@ private static DirectoryInfo DetermineWorkingDirectoryRoot()
3350
return directory ?? new DirectoryInfo(Directory.GetCurrentDirectory());
3451
}
3552

53+
/// <summary>
54+
/// Walks up from <paramref name="sourceDirectory"/> via <see cref="IFileSystem"/> until a
55+
/// <c>.git</c> directory or file (worktree pointer) is found.
56+
/// </summary>
3657
public static IDirectoryInfo? DetermineSourceDirectoryRoot(IDirectoryInfo sourceDirectory)
3758
{
38-
IDirectoryInfo? sourceRoot = null;
3959
var directory = sourceDirectory;
40-
while (directory != null && directory.GetDirectories(".git").Length == 0)
60+
while (directory != null)
4161
{
4262
if (directory.GetDirectories(".git").Length > 0)
43-
break;
63+
return directory;
4464
// support for git worktrees
4565
if (directory.GetFiles(".git").Length > 0)
46-
break;
47-
66+
return directory;
4867
directory = directory.Parent;
4968
}
50-
sourceRoot ??= directory;
51-
return sourceRoot;
69+
return null;
5270
}
5371

5472
/// <summary>Resolves the root of the main git repository, following worktree links when present. Disabled on CI.</summary>
@@ -80,18 +98,6 @@ public static IDirectoryInfo ResolveGitCommonRoot(IFileSystem fileSystem, IDirec
8098
return dir?.Parent ?? workingDirectoryRoot;
8199
}
82100

83-
private static DirectoryInfo InitGitCommonRoot()
84-
{
85-
var root = WorkingDirectoryRoot.FullName;
86-
var fs = new ScopedFileSystem(new FileSystem(), new ScopedFileSystemOptions(root)
87-
{
88-
AllowedHiddenFileNames = new HashSet<string>(StringComparer.OrdinalIgnoreCase) { ".git" },
89-
AllowedHiddenFolderNames = new HashSet<string>(StringComparer.OrdinalIgnoreCase) { ".git" }
90-
});
91-
var rootDir = fs.DirectoryInfo.New(root);
92-
return new DirectoryInfo(ResolveGitCommonRoot(fs, rootDir).FullName);
93-
}
94-
95101
/// Used in debug to locate static folder, so we can change js/css files while the server is running
96102
public static DirectoryInfo? GetSolutionDirectory()
97103
{

src/services/Elastic.Documentation.Assembler/AssembleContext.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,9 @@ public AssembleContext(
8989
Endpoints.Environment = environment;
9090

9191
var contentSource = Environment.ContentSource.ToStringFast(true);
92-
var defaultCheckoutDirectory = Path.Join(Paths.GitCommonRoot.FullName, ".artifacts", "checkouts", contentSource);
92+
var workingRoot = ReadFileSystem.DirectoryInfo.New(Paths.WorkingDirectoryRoot.FullName);
93+
var gitCommonRoot = Paths.ResolveGitCommonRoot(ReadFileSystem, workingRoot);
94+
var defaultCheckoutDirectory = Path.Join(gitCommonRoot.FullName, ".artifacts", "checkouts", contentSource);
9395
CheckoutDirectory = ReadFileSystem.DirectoryInfo.New(checkoutDirectory ?? defaultCheckoutDirectory);
9496
var defaultOutputDirectory = Path.Join(Paths.WorkingDirectoryRoot.FullName, ".artifacts", "assembly");
9597
OutputDirectory = ReadFileSystem.DirectoryInfo.New(output ?? defaultOutputDirectory);

0 commit comments

Comments
 (0)