1
1
package mill .eval
2
2
3
- import mill .api .{ExecResult , Result , Val }
4
3
import mill .api .internal .TestReporter
4
+ import mill .api .{ExecResult , Result , Val }
5
5
import mill .constants .OutFiles
6
- import mill .define .{Evaluator , InputImpl , NamedTask , SelectMode , Task , SelectiveExecution }
7
6
import mill .define .SelectiveExecution .ChangedTasks
7
+ import mill .define .*
8
8
import mill .exec .{CodeSigUtils , Execution , PlanImpl }
9
9
import mill .internal .SpanningForest
10
10
import mill .internal .SpanningForest .breadthFirst
@@ -87,26 +87,42 @@ private[mill] class SelectiveExecutionImpl(evaluator: Evaluator)
87
87
tasks,
88
88
SelectMode .Separated ,
89
89
evaluator.allowPositionalCommandArgs
90
- ).map(computeChangedTasks0(_))
90
+ ).map { tasks =>
91
+ computeChangedTasks0(tasks, SelectiveExecutionImpl .Metadata .compute(evaluator, tasks))
92
+ // If we did not have the metadata, presume everything was changed.
93
+ .getOrElse(ChangedTasks .all(tasks))
94
+ }
91
95
}
92
96
93
- def computeChangedTasks0 (tasks : Seq [NamedTask [? ]]): ChangedTasks = {
97
+ /**
98
+ * @return [[None ]] when the metadata file is empty.
99
+ * @note throws if the metadata file does not exist.
100
+ */
101
+ def computeChangedTasks0 (
102
+ tasks : Seq [NamedTask [? ]],
103
+ computedMetadata : SelectiveExecution .Metadata .Computed
104
+ ): Option [ChangedTasks ] = {
94
105
val oldMetadataTxt = os.read(evaluator.outPath / OutFiles .millSelectiveExecution)
95
106
96
- if (oldMetadataTxt == " " ) ChangedTasks (tasks, tasks.toSet, tasks, Map .empty)
97
- else {
107
+ // We allow to clear the selective execution metadata to rerun all tasks.
108
+ //
109
+ // You would think that removing the file achieves the same result, however, blanking the file indicates that
110
+ // this was intentional and you did not simply forgot to run `selective.prepare` beforehand.
111
+ if (oldMetadataTxt == " " ) None
112
+ else Some {
98
113
val transitiveNamed = PlanImpl .transitiveNamed(tasks)
99
114
val oldMetadata = upickle.default.read[SelectiveExecution .Metadata ](oldMetadataTxt)
100
- val (newMetadata, results) =
101
- SelectiveExecutionImpl .Metadata .compute0(evaluator, transitiveNamed)
102
115
val (changedRootTasks, downstreamTasks) =
103
- evaluator.selective.computeDownstream(transitiveNamed, oldMetadata, newMetadata)
116
+ evaluator.selective.computeDownstream(
117
+ transitiveNamed,
118
+ oldMetadata,
119
+ computedMetadata.metadata
120
+ )
104
121
105
122
ChangedTasks (
106
123
tasks,
107
124
changedRootTasks.collect { case n : NamedTask [_] => n },
108
- downstreamTasks.collect { case n : NamedTask [_] => n },
109
- results
125
+ downstreamTasks.collect { case n : NamedTask [_] => n }
110
126
)
111
127
}
112
128
}
@@ -174,22 +190,22 @@ private[mill] class SelectiveExecutionImpl(evaluator: Evaluator)
174
190
175
191
def computeMetadata (
176
192
tasks : Seq [NamedTask [? ]]
177
- ): ( SelectiveExecution .Metadata , Map [ Task [ ? ], ExecResult [ Val ]]) =
193
+ ): SelectiveExecution .Metadata . Computed =
178
194
SelectiveExecutionImpl .Metadata .compute(evaluator, tasks)
179
195
}
180
196
object SelectiveExecutionImpl {
181
197
object Metadata {
182
198
def compute (
183
199
evaluator : Evaluator ,
184
200
tasks : Seq [NamedTask [? ]]
185
- ): ( SelectiveExecution .Metadata , Map [ Task [ ? ], ExecResult [ Val ]]) = {
201
+ ): SelectiveExecution .Metadata . Computed = {
186
202
compute0(evaluator, PlanImpl .transitiveNamed(tasks))
187
203
}
188
204
189
205
def compute0 (
190
206
evaluator : Evaluator ,
191
207
transitiveNamed : Seq [NamedTask [? ]]
192
- ): ( SelectiveExecution .Metadata , Map [ Task [ ? ], ExecResult [ Val ]]) = {
208
+ ): SelectiveExecution .Metadata . Computed = {
193
209
val results : Map [NamedTask [? ], mill.api.Result [Val ]] = transitiveNamed
194
210
.collect { case task : InputImpl [_] =>
195
211
val ctx = new mill.define.TaskCtx .Impl (
@@ -212,10 +228,13 @@ object SelectiveExecutionImpl {
212
228
val inputHashes = results.map {
213
229
case (task, execResultVal) => (task.ctx.segments.render, execResultVal.get.value.hashCode)
214
230
}
215
- new SelectiveExecution .Metadata (
216
- inputHashes,
217
- evaluator.codeSignatures
218
- ) -> results.map { case (k, v) => (k, ExecResult .Success (v.get)) }
231
+ SelectiveExecution .Metadata .Computed (
232
+ new SelectiveExecution .Metadata (
233
+ inputHashes,
234
+ evaluator.codeSignatures
235
+ ),
236
+ results.map { case (k, v) => (k, ExecResult .Success (v.get)) }
237
+ )
219
238
}
220
239
}
221
240
0 commit comments