public/Invoke-Task.ps1
|
function Invoke-Task { <# .SYNOPSIS Executes another task in the current build script. .DESCRIPTION This is a function that will allow you to invoke a Task from within another Task in the current build script. .PARAMETER TaskName The name of the task to execute. .EXAMPLE Invoke-Task "Compile" This example calls the "Compile" task. #> [CmdletBinding()] param( [Parameter(Mandatory = $true)] [string] $TaskName ) Write-Debug "Invoke-Task: '$TaskName'" Assert $TaskName ($msgs.error_invalid_task_name) $taskKey = $TaskName.ToLower() $currentContext = $psake.Context.Peek() if ($currentContext.aliases.Contains($taskKey)) { $TaskName = $currentContext.aliases.$taskKey.Name $taskKey = $TaskName.ToLower() } Assert ($currentContext.tasks.Contains($taskKey)) ($msgs.error_task_name_does_not_exist -f $TaskName) if ($currentContext.executedTasks.Contains($taskKey)) { return } Assert (!$currentContext.callStack.Contains($taskKey)) ($msgs.error_circular_reference -f $TaskName) $currentContext.callStack.Push($taskKey) try { $task = $currentContext.tasks.$taskKey $precondition_is_valid = & $task.Precondition if (!$precondition_is_valid) { Write-BuildMessage ($msgs.precondition_was_false -f $TaskName) "heading" } else { if ($taskKey -ne 'default') { if ($task.PreAction -or $task.PostAction) { Assert ($null -ne $task.Action) ($msgs.error_missing_action_parameter -f $TaskName) } foreach ($variable in $task.requiredVariables) { Assert ((Test-Path "variable:$variable") -and ($null -ne (Get-Variable $variable).Value)) ($msgs.required_variable_not_set -f $variable, $TaskName) } if ($task.Action) { $stopwatch = New-Object System.Diagnostics.Stopwatch try { foreach ($childTask in $task.DependsOn) { Invoke-Task $childTask } $stopwatch.Start() $currentContext.currentTaskName = $TaskName try { & $currentContext.taskSetupScriptBlock @($task) try { if ($task.PreAction) { & $task.PreAction } if ($currentContext.config.taskNameFormat -is [ScriptBlock]) { $taskHeader = & $currentContext.config.taskNameFormat $TaskName } else { $taskHeader = $currentContext.config.taskNameFormat -f $TaskName } Write-BuildMessage $taskHeader "heading" & $task.Action } finally { if ($task.PostAction) { & $task.PostAction } } } catch { # want to catch errors here _before_ we invoke TaskTearDown # so that TaskTearDown reliably gets the Task-scoped # success/fail/error context. $task.Success = $false $task.ErrorMessage = $_ $task.ErrorDetail = $_ | Out-String $task.ErrorFormatted = Format-ErrorMessage $_ throw $_ # pass this up the chain; cleanup is handled higher int he stack } finally { & $currentContext.taskTearDownScriptBlock $task } } catch { if ($task.ContinueOnError) { Write-BuildMessage ("-" * 70) "warning" Write-BuildMessage ($msgs.continue_on_error -f $TaskName, $_) "warning" Write-BuildMessage ("-" * 70) "warning" } else { throw $_ } } finally { $task.Duration = $stopwatch.Elapsed } } else { # no action was specified but we still execute all the dependencies foreach ($childTask in $task.DependsOn) { Invoke-Task $childTask } } } else { foreach ($childTask in $task.DependsOn) { Invoke-Task $childTask } } Assert (& $task.PostCondition) ($msgs.postcondition_failed -f $TaskName) } } catch { throw $_ } finally { $poppedTaskKey = $currentContext.callStack.Pop() Assert ($poppedTaskKey -eq $taskKey) ($msgs.error_corrupt_callstack -f $taskKey, $poppedTaskKey) } $currentContext.executedTasks.Push($taskKey) } |