BuildInstance InternalStart(string name, OutputNode rule, BuildInstance instance)
{
// walk down the pipeline and build from the bottom-up
var currentStage = rule.GetBottomNode();
var inputNode = currentStage as InputNode;
if (!inputNode.ResolveNames(instance) || !rule.ResolveNames(instance))
return BuildFailed(name, instance);
// check to see if we even need to do this build
if (!FullRebuild && !history.ShouldBuild(instance))
{
allAssets.Add(name);
foreach (var entry in history.GetDependencies(instance.OutputName))
allAssets.Add(entry);
Log.Info("Skipping '{0}' (up-to-date).", name);
instance.Status = BuildStatus.Skipped;
Interlocked.Increment(ref Stats.Skipped);
return instance;
}
// run the pipeline
IEnumerable<object> state = null;
while (currentStage != null)
{
// run the current stage, saving the results and passing them on to the next stage in the pipeline
try
{
state = currentStage.Evaluate(instance, state);
}
catch (Exception e)
{
Log.Error("Exception thrown while building '{0}': {1}", name, e);
return BuildFailed(name, instance);
}
if (state == null)
{
if (instance.IsTempBuild && currentStage is OutputNode)
return instance;
return BuildFailed(name, instance);
}
currentStage = currentStage.OutputNode;
}
if (instance.Status == BuildStatus.Failed)
return BuildFailed(name, instance);
history.BuildSucceeded(instance);
builtAssets.Add(instance.OutputName);
allAssets.Add(instance.OutputName);
foreach (var byproduct in instance.Byproducts)
{
allAssets.Add(byproduct);
builtAssets.Add(byproduct);
}
Log.Write("Build for '{0}' successful.", name);
instance.Status = BuildStatus.Succeeded;
Interlocked.Increment(ref Stats.Succeeded);
return instance;
}