1//! See [`Job`] and [`Work`].
23use std::fmt;
4use std::mem;
56use super::JobState;
7use crate::core::compiler::fingerprint::DirtyReason;
8use crate::util::CargoResult;
910/// Represents a unit of [`Work`] with a [`Freshness`] for caller
11/// to determine whether to re-execute or not.
12pub struct Job {
13 work: Work,
14 fresh: Freshness,
15}
1617/// The basic unit of work.
18///
19/// Each proc should send its description before starting.
20/// It should send either once or close immediately.
21pub struct Work {
22 inner: Box<dyn FnOnce(&JobState<'_, '_>) -> CargoResult<()> + Send>,
23}
2425impl Work {
26/// Creates a unit of work.
27pub fn new<F>(f: F) -> Work
28where
29F: FnOnce(&JobState<'_, '_>) -> CargoResult<()> + Send + 'static,
30 {
31 Work { inner: Box::new(f) }
32 }
3334/// Creates a unit of work that does nothing.
35pub fn noop() -> Work {
36 Work::new(|_| Ok(()))
37 }
3839/// Consumes this work by running it.
40pub fn call(self, tx: &JobState<'_, '_>) -> CargoResult<()> {
41 (self.inner)(tx)
42 }
4344/// Creates a new unit of work that chains `next` after ourself.
45pub fn then(self, next: Work) -> Work {
46 Work::new(move |state| {
47self.call(state)?;
48 next.call(state)
49 })
50 }
51}
5253impl Job {
54/// Creates a new job that does nothing.
55pub fn new_fresh() -> Job {
56 Job {
57 work: Work::noop(),
58 fresh: Freshness::Fresh,
59 }
60 }
6162/// Creates a new job representing a unit of work.
63pub fn new_dirty(work: Work, dirty_reason: DirtyReason) -> Job {
64 Job {
65 work,
66 fresh: Freshness::Dirty(dirty_reason),
67 }
68 }
6970/// Consumes this job by running it, returning the result of the
71 /// computation.
72pub fn run(self, state: &JobState<'_, '_>) -> CargoResult<()> {
73self.work.call(state)
74 }
7576/// Returns whether this job was fresh/dirty, where "fresh" means we're
77 /// likely to perform just some small bookkeeping where "dirty" means we'll
78 /// probably do something slow like invoke rustc.
79pub fn freshness(&self) -> &Freshness {
80&self.fresh
81 }
8283/// Chains the given work by putting it in front of our own unit of work.
84pub fn before(&mut self, next: Work) {
85let prev = mem::replace(&mut self.work, Work::noop());
86self.work = next.then(prev);
87 }
88}
8990impl fmt::Debug for Job {
91fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
92write!(f, "Job {{ ... }}")
93 }
94}
9596/// Indication of the freshness of a package.
97///
98/// A fresh package does not necessarily need to be rebuilt (unless a dependency
99/// was also rebuilt), and a dirty package must always be rebuilt.
100#[derive(Debug, Clone)]
101pub enum Freshness {
102 Fresh,
103 Dirty(DirtyReason),
104}
105106impl Freshness {
107pub fn is_dirty(&self) -> bool {
108matches!(self, Freshness::Dirty(_))
109 }
110111pub fn is_fresh(&self) -> bool {
112matches!(self, Freshness::Fresh)
113 }
114}