journal/Journal.DevTool/Runner/TargetRunner.cs

42 lines
1.3 KiB
C#

using Sdt.Config;
namespace Sdt.Runner;
public static class TargetRunner
{
/// <summary>
/// Returns the ordered list of real (non-virtual) steps needed to execute <paramref name="target"/>,
/// respecting DependsOn chains. Each step appears at most once.
/// </summary>
public static List<BuildTarget> ResolvePlan(
BuildTarget target,
IReadOnlyDictionary<string, BuildTarget> allTargets)
{
var visited = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
var plan = new List<BuildTarget>();
Visit(target, allTargets, visited, plan);
return plan;
}
private static void Visit(
BuildTarget target,
IReadOnlyDictionary<string, BuildTarget> allTargets,
HashSet<string> visited,
List<BuildTarget> plan)
{
if (!visited.Add(target.Id))
return;
// Recurse into dependencies first (topological order)
foreach (var depId in target.DependsOn)
{
if (allTargets.TryGetValue(depId, out var dep))
Visit(dep, allTargets, visited, plan);
}
// Virtual aggregator targets (null Command) are just dependency collectors
if (target.Command is not null)
plan.Add(target);
}
}