@@ -46,6 +46,8 @@ type solution struct {
46
46
solv Solver
47
47
}
48
48
49
+ const concurrentWriters = 16
50
+
49
51
// WriteDepTree takes a basedir and a Lock, and exports all the projects
50
52
// listed in the lock to the appropriate target location within the basedir.
51
53
//
@@ -65,37 +67,91 @@ func WriteDepTree(basedir string, l Lock, sm SourceManager, sv bool, logger *log
65
67
return err
66
68
}
67
69
68
- var wg sync.WaitGroup
69
- errCh := make (chan error , len (l .Projects ()))
70
+ lps := l .Projects ()
70
71
71
- for _ , p := range l .Projects () {
72
- wg .Add (1 )
73
- go func (p LockedProject ) {
72
+ type resp struct {
73
+ i int
74
+ err error
75
+ }
76
+ respCh := make (chan resp , len (lps ))
77
+ writeCh := make (chan int , len (lps ))
78
+ cancel := make (chan struct {})
79
+
80
+ // Queue work.
81
+ for i := range lps {
82
+ writeCh <- i
83
+ }
84
+ close (writeCh )
85
+ // Launch writers.
86
+ writers := concurrentWriters
87
+ if len (lps ) < writers {
88
+ writers = len (lps )
89
+ }
90
+ var wg sync.WaitGroup
91
+ wg .Add (writers )
92
+ for i := 0 ; i < writers ; i ++ {
93
+ go func () {
74
94
defer wg .Done ()
75
- to := filepath .FromSlash (filepath .Join (basedir , string (p .Ident ().ProjectRoot )))
76
- logger .Printf ("Writing out %s@%s" , p .Ident ().errString (), p .Version ())
77
95
78
- if err := sm .ExportProject (p .Ident (), p .Version (), to ); err != nil {
79
- errCh <- errors .Wrapf (err , "failed to export %s" , p .Ident ().ProjectRoot )
80
- return
81
- }
96
+ for i := range writeCh {
97
+ select {
98
+ case <- cancel :
99
+ return
100
+ default :
101
+ }
82
102
83
- if sv {
84
- err := filepath .Walk (to , stripVendor )
85
- if err != nil {
86
- errCh <- errors .Wrapf (err , "failed to strip vendor from %s" , p .Ident ().ProjectRoot )
103
+ p := lps [i ]
104
+ to := filepath .FromSlash (filepath .Join (basedir , string (p .Ident ().ProjectRoot )))
105
+
106
+ if err := sm .ExportProject (p .Ident (), p .Version (), to ); err != nil {
107
+ respCh <- resp {i , errors .Wrapf (err , "failed to export %s" , p .Ident ().ProjectRoot )}
108
+ continue
109
+ }
110
+
111
+ if sv {
112
+ select {
113
+ case <- cancel :
114
+ return
115
+ default :
116
+ }
117
+
118
+ if err := filepath .Walk (to , stripVendor ); err != nil {
119
+ respCh <- resp {i , errors .Wrapf (err , "failed to strip vendor from %s" , p .Ident ().ProjectRoot )}
120
+ continue
121
+ }
87
122
}
123
+
124
+ respCh <- resp {i , nil }
88
125
}
89
- }(p )
126
+ }()
127
+ }
128
+ // Monitor writers
129
+ go func () {
130
+ wg .Wait ()
131
+ close (respCh )
132
+ }()
133
+
134
+ // Log results and collect errors
135
+ var errs []error
136
+ var cnt int
137
+ for resp := range respCh {
138
+ cnt ++
139
+ msg := "Wrote"
140
+ if resp .err != nil {
141
+ if len (errs ) == 0 {
142
+ close (cancel )
143
+ }
144
+ errs = append (errs , resp .err )
145
+ msg = "Failed to write"
146
+ }
147
+ p := lps [resp .i ]
148
+ logger .Printf ("(%d/%d) %s %s@%s\n " , cnt , len (lps ), msg , p .Ident (), p .Version ())
90
149
}
91
150
92
- wg .Wait ()
93
- close (errCh )
94
-
95
- if len (errCh ) > 0 {
151
+ if len (errs ) > 0 {
96
152
logger .Println ("Failed to write dep tree. The following errors occurred:" )
97
- for err := range errCh {
98
- logger .Println ( " * " , err )
153
+ for i , err := range errs {
154
+ logger .Printf ( "(%d/%d) %s \n " , i + 1 , len ( errs ) , err )
99
155
}
100
156
101
157
os .RemoveAll (basedir )
0 commit comments