6
6
"io"
7
7
"os"
8
8
"strings"
9
+ "sync"
9
10
)
10
11
11
12
const (
@@ -14,16 +15,37 @@ const (
14
15
remoteDigestPrefix = "latest: digest: sha256:"
15
16
)
16
17
18
+ var (
19
+ DigestOutputError = digestOutputError {
20
+ errors .New ("no digest in output found" ),
21
+ }
22
+ )
23
+
24
+ type digestOutputError struct {
25
+ error
26
+ }
27
+
28
+ func (err digestOutputError ) Is (other error ) bool {
29
+ _ , ok := other .(digestOutputError )
30
+ return ok
31
+ }
32
+
17
33
// Push calls docker and pushes a tag.
18
34
// Returns the remote digest for the pushed image.
19
35
func PushWithWriters (tag string , out io.Writer , errOut io.Writer ) (string , error ) {
20
36
r , w := io .Pipe ()
21
37
defer r .Close ()
22
38
defer w .Close ()
23
39
24
- digest := make (chan string )
25
- defer close (digest )
40
+ digest := make (chan string , 1 )
41
+ errs := make (chan error , 1 )
42
+ errG := sync.WaitGroup {}
43
+
44
+ errG .Add (1 )
26
45
go func () {
46
+ defer close (digest )
47
+ defer errG .Done ()
48
+
27
49
scanner := bufio .NewScanner (r )
28
50
for scanner .Scan () {
29
51
if ! strings .HasPrefix (scanner .Text (), remoteDigestPrefix ) {
@@ -33,18 +55,32 @@ func PushWithWriters(tag string, out io.Writer, errOut io.Writer) (string, error
33
55
digest <- scanner .Text ()[len (remoteDigestPrefix ) : len (remoteDigestPrefix )+ 64 ]
34
56
return
35
57
}
58
+ errs <- DigestOutputError
36
59
}()
37
- err := executeDockerCommandWithWriters (io .MultiWriter (out , w ), errOut , "push" , tag )
38
- if err != nil {
39
- return "" , err
40
- }
41
60
42
- select {
43
- case d := <- digest :
61
+ errG .Add (1 )
62
+ go func () {
63
+ defer errG .Done ()
64
+
65
+ errs <- executeDockerCommandWithWriters (io .MultiWriter (out , w ), errOut , "push" , tag )
66
+ }()
67
+
68
+ go func () {
69
+ defer close (errs )
70
+
71
+ errG .Wait ()
72
+ }()
73
+
74
+ d , ok := <- digest
75
+ if ok {
44
76
return d , nil
45
- default :
46
- return "" , errors .New ("no digest in output found" )
47
77
}
78
+ for err := range errs {
79
+ if err != nil {
80
+ return "" , err
81
+ }
82
+ }
83
+ panic ("should have resulted in error before" )
48
84
}
49
85
50
86
// Push calls docker and pushes a tag.
0 commit comments