@@ -61,6 +61,10 @@ impl Plan {
61
61
* self = Plan :: new ( ) ;
62
62
}
63
63
64
+ pub fn is_ready ( & self ) -> bool {
65
+ self . compiler_jobs . is_empty ( ) == false
66
+ }
67
+
64
68
/// Cache a given compiler invocation in `ProcessBuilder` for a given
65
69
/// `PackageId` and `TargetKind` in `Target`, to be used when processing
66
70
/// cached build plan.
@@ -194,6 +198,36 @@ impl Plan {
194
198
. collect ( )
195
199
}
196
200
201
+ /// Returns a topological ordering of a connected DAG of rev deps. The
202
+ /// output is a stack of units that can be linearly rebuilt, starting from
203
+ /// the last element.
204
+ fn topological_sort ( & self , dirties : & HashMap < UnitKey , HashSet < UnitKey > > ) -> Vec < UnitKey > {
205
+ let mut visited: HashSet < UnitKey > = HashSet :: new ( ) ;
206
+ let mut output = vec ! [ ] ;
207
+
208
+ for ( k, _) in dirties {
209
+ if !visited. contains ( & k) {
210
+ dfs ( k, & self . rev_dep_graph , & mut visited, & mut output) ;
211
+ }
212
+ }
213
+
214
+ return output;
215
+
216
+ // Process graph depth-first recursively. A node needs to be pushed
217
+ // after processing every other before to ensure topological ordering.
218
+ fn dfs ( unit : & UnitKey , graph : & HashMap < UnitKey , HashSet < UnitKey > > ,
219
+ visited : & mut HashSet < UnitKey > , output : & mut Vec < UnitKey > ) {
220
+ if visited. contains ( & unit) { return ; }
221
+ else {
222
+ visited. insert ( unit. clone ( ) ) ;
223
+ for neighbour in graph. get ( & unit) . unwrap ( ) {
224
+ dfs ( neighbour, graph, visited, output) ;
225
+ }
226
+ output. push ( unit. clone ( ) ) ;
227
+ }
228
+ }
229
+ }
230
+
197
231
pub fn prepare_work < T : AsRef < Path > + fmt:: Debug > ( & self , modified : & [ T ] ) -> WorkStatus {
198
232
let dirties = self . fetch_dirty_units ( modified) ;
199
233
trace ! ( "fetch_dirty_units: for files {:?}, these units are dirty: {:?}" , modified, dirties) ;
@@ -204,10 +238,13 @@ impl Plan {
204
238
let graph = self . dirty_rev_dep_graph ( & dirties) ;
205
239
trace ! ( "Constructed dirty rev dep graph: {:?}" , graph) ;
206
240
207
- // TODO: Then sort topologically the deps
208
- // TODO: Then map those with a ProcessBuilder
241
+ let queue = self . topological_sort ( & graph) ;
242
+ trace ! ( "Topologically sorted dirty graph: {:?}" , queue) ;
243
+ let jobs = queue. iter ( )
244
+ . map ( |x| self . compiler_jobs . get ( x) . unwrap ( ) . clone ( ) )
245
+ . collect ( ) ;
209
246
210
- WorkStatus :: Execute ( JobQueue { } )
247
+ WorkStatus :: Execute ( JobQueue ( jobs ) )
211
248
}
212
249
}
213
250
}
@@ -217,8 +254,12 @@ pub enum WorkStatus {
217
254
Execute ( JobQueue )
218
255
}
219
256
220
- pub struct JobQueue {
257
+ pub struct JobQueue ( Vec < ProcessBuilder > ) ;
221
258
259
+ impl JobQueue {
260
+ pub fn dequeue ( & mut self ) -> Option < ProcessBuilder > {
261
+ self . 0 . pop ( )
262
+ }
222
263
}
223
264
224
265
fn key_from_unit ( unit : & Unit ) -> UnitKey {
0 commit comments