1
+ using System . Collections . ObjectModel ;
2
+
1
3
namespace IntelliTect . Multitool ;
4
+
2
5
/// <summary>
3
6
/// Provides consistent environment-independent normalized pathing within a repository.
4
7
/// </summary>
5
8
public static class RepositoryPaths
6
9
{
7
10
/// <summary>
8
- /// Finds the root of the repository by looking for the .git folder.
11
+ /// Name of the build variables file that is created by the build process.
12
+ /// </summary>
13
+ public const string BuildVariableFileName = "IntelliTect.MultiTool.BuildVariables.tmp" ;
14
+
15
+ /// <summary>
16
+ /// Holds the key value pairs of the build variables that this class can use.
17
+ /// </summary>
18
+ public static ReadOnlyDictionary < string , string ? > BuildVariables { get ; } = new ( File . ReadAllLines ( Path . Combine ( Path . GetTempPath ( ) , BuildVariableFileName ) )
19
+ . Select ( line => line . Split ( "::" ) )
20
+ . ToDictionary ( split => split [ 0 ] . Trim ( ) ,
21
+ split => ! string . IsNullOrEmpty ( split [ 1 ] ) ? split [ 1 ] . Trim ( ) : null ) ) ;
22
+
23
+ /// <summary>
24
+ /// Finds the root of the repository by looking for the directory containing the .git directory.
25
+ /// Begins searching up from the current directory, and retries from the project directory if initially not found.
26
+ /// Defaults to the solution directory, if available, if the .git directory is not found.
9
27
/// </summary>
10
28
/// <returns>Full path to repo root.</returns>
11
29
public static string GetDefaultRepoRoot ( )
12
30
{
13
- DirectoryInfo ? currentDirectory = new ( Directory . GetCurrentDirectory ( ) ) ;
31
+ string gitDirectory ;
32
+ DirectoryInfo ? searchStartDirectory ;
14
33
15
- while ( currentDirectory is not null )
34
+ // If not live unit testing, try searching from current directory. But if we are this will fail, so just skip
35
+ if ( ! ( BuildVariables . TryGetValue ( "BuildingForLiveUnitTesting" , out string ? isLiveUnitTesting )
36
+ && isLiveUnitTesting == "true" ) )
16
37
{
17
- DirectoryInfo [ ] subDirectories = currentDirectory . GetDirectories ( ".git" ) ;
18
- if ( subDirectories . Length > 0 )
38
+ searchStartDirectory = new ( Directory . GetCurrentDirectory ( ) ) ;
39
+ if ( TrySearchForGitContainingDirectory ( searchStartDirectory , out gitDirectory )
40
+ && ! string . IsNullOrWhiteSpace ( gitDirectory ) )
19
41
{
20
- return currentDirectory . FullName ;
42
+ return gitDirectory ;
21
43
}
22
-
23
- currentDirectory = currentDirectory . Parent ;
24
44
}
25
-
45
+ // Search from the project directory if we are live unit testing or if the initial search failed.
46
+ if ( BuildVariables . TryGetValue ( "ProjectPath" , out string ? projectPath ) )
47
+ {
48
+ searchStartDirectory = new FileInfo ( projectPath ) . Directory ;
49
+ if ( TrySearchForGitContainingDirectory ( searchStartDirectory , out gitDirectory )
50
+ && ! string . IsNullOrWhiteSpace ( gitDirectory ) )
51
+ {
52
+ return gitDirectory ;
53
+ }
54
+ }
55
+ // If all this fails, try returning the Solution Directory in hopes that is in the root of the repo.
56
+ if ( BuildVariables . TryGetValue ( "SolutionDir" , out string ? solutionDir ) && ! string . IsNullOrWhiteSpace ( solutionDir ) )
57
+ {
58
+ return Directory . Exists ( solutionDir ) ? solutionDir : throw new InvalidOperationException ( $ "SolutionDir is not a valid directory.") ;
59
+ }
26
60
throw new InvalidOperationException ( "Could not find the repo root directory from the current directory. Current directory is expected to be the repoRoot sub directory." ) ;
27
61
}
62
+
63
+ /// <summary>
64
+ /// Searches up from the <paramref name="searchStartDirectory"/> looking for a .git directory.
65
+ /// </summary>
66
+ /// <param name="searchStartDirectory">The directory to start searching from, will search up.</param>
67
+ /// <param name="gitParentDirectory">The parent directory to the .git directory.</param>
68
+ /// <returns><c>true</c> if the directory <paramref name="gitParentDirectory" /> was found successfully; otherwise, false.</returns>
69
+ public static bool TrySearchForGitContainingDirectory ( DirectoryInfo ? searchStartDirectory , out string gitParentDirectory )
70
+ {
71
+ while ( searchStartDirectory is not null )
72
+ {
73
+ DirectoryInfo [ ] subDirectories = searchStartDirectory . GetDirectories ( ".git" ) ;
74
+ if ( subDirectories . Length > 0 )
75
+ {
76
+ gitParentDirectory = searchStartDirectory . FullName ;
77
+ return true ;
78
+ }
79
+
80
+ searchStartDirectory = searchStartDirectory . Parent ;
81
+ }
82
+ gitParentDirectory = string . Empty ;
83
+ return false ;
84
+ }
28
85
}
0 commit comments