This page provides information for developers.

# Tasks

## What is a task ?

A task is the **basic execution unit** in provs. When executed, each task produces exactly one result (line) with either success or failure.

The success or failure is computed automatically in the following way:
* a **task** fails if it calls subtasks and if at least one subtask has failed
* a **taskWithResult** works the same except that it requires an additional result to be returned which is also included in the success calculation
* a task defined with **optional** (i.e. `= optional { /* ... */ }` always returns success (even if there are failing subtasks)
* **requireLast** defines a task which must provide an explicit result and solely this result counts for success calculation

## Task declaration 

### Recommended way

A task can be declared by

```kotlin
fun Prov.myCustomTask() = task { /* ... code and subtasks come here ... */ }

// e.g.
fun Prov.myEchoTask() = task {
    cmd("echo hello world!")
}
```

The task will succeed if all sub-tasks (called tasks during execution) have succeeded resp. if no sub-task was called.  

### Alternative ways

The following ways are equivalent but are more verbose:

```kotlin
// Redundant declaration of the return type (ProvResult), which is already declared by task
fun Prov.myCustomTask(): ProvResult = task { /* ... code and subtasks come here ... */ }

// Redundant parentheses behind task
fun Prov.myCustomTask() = task() { /* ... code and subtasks come here ... */ }

// Redundant definition of the task name, but could be used to output a different task name  
fun Prov.myCustomTask() = task("myCustomTask") { /* ... code and subtasks come here ... */ }

// Functionally equal, but with additional curly brackets 
fun Prov.myCustomTask() { task { /* ... code and subtasks come here ... */ } }
```

Btw, the following lines and WILL NOT work as expected. 
Due to too much lamda nesting, the code within the task is NOT executed:

```kotlin
fun Prov.myCustomTask() = { task { /* ... code and subtasks come here ... */ } }
fun Prov.myCustomTask() {{ task { /* ... code and subtasks come here ... */ } }}
```

### Add custom results

If you want to add a result explicitly, you can use method `addResult`.
This may be used e.g. to add explicitly an error line or with additional info, like in: 

```kotlin
fun Prov.myCustomTask() = task {
    /* some other code ... */
    addResult(false, err = "my error msg")
    /* some other code ... */
    addResult(true, info = "package was already installed")
}
```
or alternatively you can use `taskWithResult` and `return@taskWithResult ProvResult(false, err = "my error msg")`.

#### TaskWithResult

In case you want to include the return value (of type `ProvResult`) of a task to be added to the evaluation, 
you can use `taskWithResult` instead of `task` and return the value, e.g. like 

```kotlin
fun Prov.myEchoTask() = taskWithResult { 
    cmd("echo hello world!") 
    // ...
    ProvResult(false, "Error: ... error message ...")  // will be the returned as return value and included in the evaluation 
}
```

IMPORTANT: the value you want to return must be placed at the end of the lambda code (as usual in functional programming)!
The following will NOT work as expected:

```kotlin
fun Prov.myEchoTask() = taskWithResult {
    ProvResult(false, "Error: ... error message ...")  // will be ignored
    // the result from the call below (i.e. from task "cmd") will be returned by myEchoTask,
    // which is redundant as its result is already included in the evaluation anyway. 
    cmd("echo hello world!")  
}
```


### Task output

If a task is run e.g. with `local().myEchoTask()`, it will produce output like
```
>  Success -- myEchoTask 
--->  Success -- cmd [/bin/bash, -c, echo hello world!]
```


## Call hierarchy

In the following link you can find an example of a sequence diagram when provisioning a desktop:

[ProvisionDesktopSequence.md](ProvisionDesktopSequence.md)


## Create a provs jar-file

* Clone this repo
* Build the jar-file by `./gradlew uberjarDesktop`
* In folder build/libs you'll find the file `provs-desktop.jar`

This uberjar is a Java jar-file including all required dependencies.