1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
use {
crate::*,
anyhow::{
Result,
anyhow,
},
};
/// The stack of jobs that bacon ran, allowing to get back to the previous one,
/// or to scope the current one
#[derive(Default)]
pub struct JobStack {
entries: Vec<ConcreteJobRef>,
}
impl JobStack {
/// Apply the job ref instruction to determine the job to run, updating the stack.
///
/// When no job is returned, the application is supposed to quit.
pub fn pick_job(
&mut self,
job_ref: &JobRef,
settings: &Settings,
) -> Result<Option<(ConcreteJobRef, Job)>> {
debug!("picking job {job_ref:?}");
let concrete = match job_ref {
JobRef::Default => settings.default_job.clone(),
JobRef::Initial => settings
.arg_job
.as_ref()
.unwrap_or(&settings.default_job)
.clone(),
JobRef::Previous | JobRef::PreviousOrQuit => {
let current = self.entries.pop();
match self.entries.pop() {
Some(concrete) => concrete,
None if current
.as_ref()
.is_some_and(|current| current.scope.has_tests()) =>
{
// rather than quitting, we assume the user wants to "unscope"
ConcreteJobRef {
#[expect(
clippy::missing_panics_doc,
reason = "checked in match guard"
)]
name_or_alias: current.unwrap().name_or_alias,
scope: Scope::default(),
}
}
None if *job_ref == JobRef::PreviousOrQuit => {
return Ok(None);
}
None => {
let Some(current) = current else {
error!("no current job"); // job stack was misused
return Ok(None);
};
current
}
}
}
JobRef::Concrete(concrete) => concrete.clone(),
JobRef::Scope(scope) => match self.entries.last() {
Some(concrete) => ConcreteJobRef {
name_or_alias: concrete.name_or_alias.clone(),
scope: scope.clone(),
},
None => {
return Ok(None);
}
},
};
let job = match &concrete.name_or_alias {
NameOrAlias::Alias(alias) => Job::from_alias(alias, settings),
NameOrAlias::Name(name) => settings
.jobs
.get(name)
.ok_or_else(|| anyhow!("job not found: {name:?}"))?
.clone(),
};
if self.entries.last() != Some(&concrete) {
self.entries.push(concrete.clone());
}
Ok(Some((concrete, job)))
}
}