dotnet run always evaluates the Aspire graph. A second launch after Ctrl+C should not wait on that. Co-authored-by: Cursor <cursoragent@cursor.com>
106 lines
2.9 KiB
C#
106 lines
2.9 KiB
C#
namespace HSchool.AppHost.Tests;
|
|
|
|
/// <summary>
|
|
/// Same rules as <c>tools/apphost-uptodate.ps1</c>. Keep the two in sync.
|
|
/// </summary>
|
|
internal static class LaunchBuildStamp
|
|
{
|
|
public const string TargetFramework = "net10.0";
|
|
|
|
public static readonly string[] InputExtensions = [".cs", ".csproj", ".props"];
|
|
|
|
public static readonly string[] NamedInputs =
|
|
[
|
|
"global.json",
|
|
"Directory.Build.props",
|
|
"Directory.Packages.props",
|
|
];
|
|
|
|
public static readonly string[] SkipDirectoryNames = ["bin", "obj", "node_modules"];
|
|
|
|
public static readonly string[] OutputProjects = ["HSchool.AppHost", "HSchool.Server"];
|
|
|
|
public static bool NeedsBuild(string repoRoot, string configuration = "Debug")
|
|
{
|
|
ArgumentException.ThrowIfNullOrWhiteSpace(repoRoot);
|
|
ArgumentException.ThrowIfNullOrWhiteSpace(configuration);
|
|
|
|
DateTime? oldestOutput = null;
|
|
foreach (var project in OutputProjects)
|
|
{
|
|
var dll = Path.Combine(
|
|
repoRoot,
|
|
"src",
|
|
project,
|
|
"bin",
|
|
configuration,
|
|
TargetFramework,
|
|
project + ".dll");
|
|
if (!File.Exists(dll))
|
|
{
|
|
return true;
|
|
}
|
|
|
|
var written = File.GetLastWriteTimeUtc(dll);
|
|
if (oldestOutput is null || written < oldestOutput.Value)
|
|
{
|
|
oldestOutput = written;
|
|
}
|
|
}
|
|
|
|
if (oldestOutput is null)
|
|
{
|
|
return true;
|
|
}
|
|
|
|
var cutoff = oldestOutput.Value;
|
|
|
|
foreach (var name in NamedInputs)
|
|
{
|
|
var path = Path.Combine(repoRoot, name);
|
|
if (File.Exists(path) && File.GetLastWriteTimeUtc(path) > cutoff)
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
|
|
var src = Path.Combine(repoRoot, "src");
|
|
return !Directory.Exists(src) || HasNewerInput(src, cutoff);
|
|
}
|
|
|
|
private static bool HasNewerInput(string directory, DateTime cutoff)
|
|
{
|
|
foreach (var file in Directory.EnumerateFiles(directory))
|
|
{
|
|
if (!IsInputExtension(Path.GetExtension(file)))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
if (File.GetLastWriteTimeUtc(file) > cutoff)
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
|
|
foreach (var child in Directory.EnumerateDirectories(directory))
|
|
{
|
|
var leaf = Path.GetFileName(child);
|
|
if (SkipDirectoryNames.Contains(leaf, StringComparer.OrdinalIgnoreCase))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
if (HasNewerInput(child, cutoff))
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
private static bool IsInputExtension(string extension) =>
|
|
InputExtensions.Contains(extension, StringComparer.OrdinalIgnoreCase);
|
|
}
|