forked from vmware-archive/atc
/
on_success.go
98 lines (81 loc) · 2.14 KB
/
on_success.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
package exec
import "os"
// OnSuccessStep will run one step, and then a second step if the first step
// succeeds.
type OnSuccessStep struct {
stepFactory StepFactory
successFactory StepFactory
prev Step
repo *SourceRepository
step Step
success Step
}
// OnSuccess constructs an OnSuccessStep factory.
func OnSuccess(firstStep StepFactory, secondStep StepFactory) OnSuccessStep {
return OnSuccessStep{
stepFactory: firstStep,
successFactory: secondStep,
}
}
// Using constructs an *OnSuccessStep.
func (o OnSuccessStep) Using(prev Step, repo *SourceRepository) Step {
o.repo = repo
o.prev = prev
o.step = o.stepFactory.Using(o.prev, o.repo)
return &o
}
// Run will call Run on the first step and wait for it to complete. If the
// first step errors, Run returns the error. OnSuccessStep is ready as soon as
// the first step is ready.
//
// If the first step succeeds (that is, its Success result is true), the second
// step is executed. If the second step errors, its error is returned.
func (o *OnSuccessStep) Run(signals <-chan os.Signal, ready chan<- struct{}) error {
stepRunErr := o.step.Run(signals, ready)
if stepRunErr != nil {
return stepRunErr
}
var success Success
_ = o.step.Result(&success)
if !success {
return nil
}
o.success = o.successFactory.Using(o.step, o.repo)
err := o.success.Run(signals, make(chan struct{}))
return err
}
// Result indicates Success as true if the first step completed and the second
// step completed successfully.
//
// Any other type is ignored.
func (o *OnSuccessStep) Result(x interface{}) bool {
switch v := x.(type) {
case *Success:
if o.success == nil {
// no second step means we must have failed the first step
*v = false
return true
}
stepResult := o.step.Result(v)
if !stepResult {
return false
}
//TODO: reset value of x when we cannot compare in the successStep.Result
successResult := o.success.Result(v)
if !successResult {
return false
}
return true
default:
return false
}
}
// Release releases both steps.
func (o *OnSuccessStep) Release() {
if o.step != nil {
o.step.Release()
}
if o.success != nil {
o.success.Release()
}
}