Skip to content

Commit 4f948f3

Browse files
feat: Support Live Unit Testing (#97)
1 parent 89f62e9 commit 4f948f3

File tree

5 files changed

+100
-13
lines changed

5 files changed

+100
-13
lines changed

IntelliTect.Multitool.Tests/IntelliTect.Multitool.Tests.csproj

+1-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
<Project Sdk="Microsoft.NET.Sdk">
1+
<Project Sdk="Microsoft.NET.Sdk">
22

33
<Import Project="../IntelliTect.Multitool/Build/IntelliTect.Multitool.targets" />
44
<PropertyGroup>
@@ -21,5 +21,4 @@
2121
<ItemGroup>
2222
<ProjectReference Include="..\IntelliTect.Multitool\IntelliTect.Multitool.csproj" />
2323
</ItemGroup>
24-
2524
</Project>

IntelliTect.Multitool.Tests/ReleaseDateAttribute.Tests.cs

+1-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
1-
using System;
2-
using Xunit;
1+
using Xunit;
32

43
namespace IntelliTect.Multitool.Tests;
54

IntelliTect.Multitool.Tests/RepositoryPaths.Tests.cs

+16
Original file line numberDiff line numberDiff line change
@@ -10,4 +10,20 @@ public void GetDefaultRepoRoot_ReturnsRepoRootDirectory()
1010
// Makes the assumption that the repository directory for this solution is named the same as the solution
1111
Assert.EndsWith(nameof(Multitool), RepositoryPaths.GetDefaultRepoRoot());
1212
}
13+
14+
[Fact]
15+
public void BuildVariables_BeingSetProperly()
16+
{
17+
Assert.Equal(3, RepositoryPaths.BuildVariables.Count);
18+
19+
Assert.True(RepositoryPaths.BuildVariables.TryGetValue("BuildingForLiveUnitTesting", out _));
20+
21+
Assert.True(RepositoryPaths.BuildVariables.TryGetValue("ProjectPath", out string? projectPath));
22+
Assert.NotNull(projectPath);
23+
Assert.NotEmpty(projectPath);
24+
25+
Assert.True(RepositoryPaths.BuildVariables.TryGetValue("SolutionDir", out string? solutionDir));
26+
Assert.NotNull(solutionDir);
27+
Assert.NotEmpty(solutionDir);
28+
}
1329
}

IntelliTect.Multitool/Build/IntelliTect.Multitool.targets

+16
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,20 @@
44
<_Parameter1>$([System.DateTime]::UtcNow.ToString("O"))</_Parameter1>
55
</AssemblyAttribute>
66
</ItemGroup>
7+
8+
<Target Name="WriteLaunchers" AfterTargets="CopyFilesToOutputDirectory">
9+
<PropertyGroup>
10+
<TempStagingPath Condition="'$(TempStagingPath)' == ''">$([System.IO.Path]::GetTempPath())</TempStagingPath>
11+
<LUTInformation>
12+
BuildingForLiveUnitTesting::$(BuildingForLiveUnitTesting)
13+
SolutionDir::$(SolutionDir)
14+
ProjectPath::$(ProjectPath)
15+
</LUTInformation>
16+
</PropertyGroup>
17+
18+
<WriteLinesToFile
19+
File="$(TempStagingPath)\IntelliTect.MultiTool.BuildVariables.tmp"
20+
Overwrite="true"
21+
Lines="$(LUTInformation)" />
22+
</Target>
723
</Project>
+66-9
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,85 @@
1+
using System.Collections.ObjectModel;
2+
13
namespace IntelliTect.Multitool;
4+
25
/// <summary>
36
/// Provides consistent environment-independent normalized pathing within a repository.
47
/// </summary>
58
public static class RepositoryPaths
69
{
710
/// <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.
927
/// </summary>
1028
/// <returns>Full path to repo root.</returns>
1129
public static string GetDefaultRepoRoot()
1230
{
13-
DirectoryInfo? currentDirectory = new(Directory.GetCurrentDirectory());
31+
string gitDirectory;
32+
DirectoryInfo? searchStartDirectory;
1433

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"))
1637
{
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))
1941
{
20-
return currentDirectory.FullName;
42+
return gitDirectory;
2143
}
22-
23-
currentDirectory = currentDirectory.Parent;
2444
}
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+
}
2660
throw new InvalidOperationException("Could not find the repo root directory from the current directory. Current directory is expected to be the repoRoot sub directory.");
2761
}
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+
}
2885
}

0 commit comments

Comments
 (0)