Skip to content

Commit ca2d265

Browse files
author
Niko Matsakis
committed
clarify status and pretty print
1 parent d88af32 commit ca2d265

File tree

20 files changed

+201
-154
lines changed

20 files changed

+201
-154
lines changed

crates/mdbook-goals/src/mdbook_preprocessor.rs

Lines changed: 47 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,6 @@ impl Preprocessor for GoalPreprocessor {
3737

3838
pub struct GoalPreprocessorWithContext<'c> {
3939
team_asks: &'static Regex,
40-
goal_list: &'static Regex,
4140
goal_count: &'static Regex,
4241
username: &'static Regex,
4342
ctx: &'c PreprocessorContext,
@@ -116,7 +115,6 @@ impl<'c> GoalPreprocessorWithContext<'c> {
116115
Ok(GoalPreprocessorWithContext {
117116
ctx,
118117
team_asks: &re::TEAM_ASKS,
119-
goal_list: &re::GOAL_LIST,
120118
goal_count: &re::GOAL_COUNT,
121119
username: &re::USERNAME,
122120
links,
@@ -163,7 +161,7 @@ impl<'c> GoalPreprocessorWithContext<'c> {
163161

164162
let count = goals
165163
.iter()
166-
.filter(|g| g.metadata.status != Status::NotAccepted)
164+
.filter(|g| g.metadata.status.is_not_not_accepted())
167165
.count();
168166

169167
chapter.content = self
@@ -175,54 +173,54 @@ impl<'c> GoalPreprocessorWithContext<'c> {
175173
}
176174

177175
fn replace_goal_lists(&mut self, chapter: &mut Chapter) -> anyhow::Result<()> {
178-
let Some(m) = self.goal_list.captures(&chapter.content) else {
179-
return Ok(());
180-
};
181-
let range = m.get(0).unwrap().range();
182-
let statuses = m[1]
183-
.split(',')
184-
.map(|s| s.trim())
185-
.map(Status::try_from)
186-
.collect::<anyhow::Result<Vec<Status>>>()?;
187-
188-
let Some(chapter_path) = &chapter.path else {
189-
anyhow::bail!("found `<!-- GOALS -->` but chapter has no path")
190-
};
191-
192-
// Extract out the list of goals with the given status.
193-
let goals = self.goal_documents(chapter_path)?;
194-
let mut goals_with_status: Vec<&GoalDocument> = statuses
195-
.iter()
196-
.flat_map(|&status| goals.iter().filter(move |g| g.metadata.status == status))
197-
.collect();
198-
199-
goals_with_status.sort_by_key(|g| &g.metadata.title);
200-
201-
// Format the list of goals and replace the `<!-- -->` comment with that.
202-
let output = goal::format_goal_table(&goals_with_status)?;
203-
chapter.content.replace_range(range, &output);
204-
205-
// Populate with children if this is not README
206-
if chapter_path.file_stem() != Some("README".as_ref()) {
207-
let mut parent_names = chapter.parent_names.clone();
208-
parent_names.push(chapter.name.clone());
209-
for (goal, index) in goals_with_status.iter().zip(0..) {
210-
let content = std::fs::read_to_string(&goal.path)
211-
.with_context(|| format!("reading `{}`", goal.path.display()))?;
212-
let path = goal.path.strip_prefix(&self.ctx.config.book.src).unwrap();
213-
let mut new_chapter =
214-
Chapter::new(&goal.metadata.title, content, path, parent_names.clone());
215-
216-
if let Some(mut number) = chapter.number.clone() {
217-
number.0.push(index + 1);
218-
new_chapter.number = Some(number);
176+
self.replace_goal_lists_helper(chapter, &re::FLAGSHIP_GOAL_LIST, |status| status.is_flagship && status.is_not_not_accepted())?;
177+
self.replace_goal_lists_helper(chapter, &re::OTHER_GOAL_LIST, |status| !status.is_flagship && status.is_not_not_accepted())?;
178+
self.replace_goal_lists_helper(chapter, &re::GOAL_LIST, |status| status.is_not_not_accepted())?;
179+
self.replace_goal_lists_helper(chapter, &re::GOAL_NOT_ACCEPTED_LIST, |status| !status.is_not_not_accepted())?;
180+
Ok(())
181+
}
182+
183+
fn replace_goal_lists_helper(&mut self, chapter: &mut Chapter, regex: &Regex, filter: impl Fn(Status) -> bool) -> anyhow::Result<()> {
184+
loop {
185+
let Some(m) = regex.find(&chapter.content) else {
186+
return Ok(());
187+
};
188+
let range = m.range();
189+
190+
let Some(chapter_path) = &chapter.path else {
191+
anyhow::bail!("found `{regex}` but chapter has no path")
192+
};
193+
194+
// Extract out the list of goals with the given status.
195+
let goals = self.goal_documents(chapter_path)?;
196+
let mut goals_with_status: Vec<&GoalDocument> = goals.iter().filter(|g| filter(g.metadata.status)).collect();
197+
198+
goals_with_status.sort_by_key(|g| &g.metadata.title);
199+
200+
// Format the list of goals and replace the `<!-- -->` comment with that.
201+
let output = goal::format_goal_table(&goals_with_status)?;
202+
chapter.content.replace_range(range, &output);
203+
204+
// Populate with children if this is not README
205+
if chapter_path.file_stem() != Some("README".as_ref()) {
206+
let mut parent_names = chapter.parent_names.clone();
207+
parent_names.push(chapter.name.clone());
208+
for (goal, index) in goals_with_status.iter().zip(0..) {
209+
let content = std::fs::read_to_string(&goal.path)
210+
.with_context(|| format!("reading `{}`", goal.path.display()))?;
211+
let path = goal.path.strip_prefix(&self.ctx.config.book.src).unwrap();
212+
let mut new_chapter =
213+
Chapter::new(&goal.metadata.title, content, path, parent_names.clone());
214+
215+
if let Some(mut number) = chapter.number.clone() {
216+
number.0.push(index + 1);
217+
new_chapter.number = Some(number);
218+
}
219+
220+
chapter.sub_items.push(BookItem::Chapter(new_chapter));
219221
}
220-
221-
chapter.sub_items.push(BookItem::Chapter(new_chapter));
222222
}
223223
}
224-
225-
self.replace_goal_lists(chapter)
226224
}
227225

228226
/// Look for `<!-- TEAM ASKS -->` in the chapter content and replace it with the team asks.
@@ -239,7 +237,7 @@ impl<'c> GoalPreprocessorWithContext<'c> {
239237
let goals = self.goal_documents(path)?;
240238
let asks_of_any_team: Vec<&TeamAsk> = goals
241239
.iter()
242-
.filter(|g| g.metadata.status != Status::NotAccepted)
240+
.filter(|g| g.metadata.status.is_not_not_accepted())
243241
.flat_map(|g| &g.team_asks)
244242
.collect();
245243
let format_team_asks = format_team_asks(&asks_of_any_team)?;

crates/rust-project-goals-cli/src/rfc.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ use rust_project_goals::{
1818
},
1919
labels::GhLabel,
2020
},
21-
goal::{self, GoalDocument, GoalPlan, ParsedOwners, Status},
21+
goal::{self, GoalDocument, GoalPlan, ParsedOwners},
2222
team::{get_person_data, TeamName},
2323
};
2424

@@ -305,7 +305,7 @@ fn issue<'doc>(timeframe: &str, document: &'doc GoalDocument) -> anyhow::Result<
305305
}
306306

307307
let mut labels = vec!["C-tracking-issue".to_string()];
308-
if let Status::Flagship = document.metadata.status {
308+
if document.metadata.status.is_flagship {
309309
labels.push("Flagship Goal".to_string());
310310
}
311311
for team in document.teams_with_asks() {

crates/rust-project-goals/src/goal.rs

Lines changed: 61 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -125,11 +125,10 @@ impl GoalDocument {
125125

126126
let link_path = Arc::new(link_path.to_path_buf());
127127

128-
let goal_plans = match metadata.status {
129-
Status::Flagship | Status::Accepted | Status::Proposed => {
130-
extract_plan_items(&sections)?
131-
}
132-
Status::NotAccepted => vec![],
128+
let goal_plans = if metadata.status.is_not_not_accepted() {
129+
extract_plan_items(&sections)?
130+
} else {
131+
vec![]
133132
};
134133

135134
let mut team_asks = vec![];
@@ -164,10 +163,7 @@ impl GoalDocument {
164163

165164
/// True if this goal is a candidate (may yet be accepted)
166165
pub fn is_not_not_accepted(&self) -> bool {
167-
match self.metadata.status {
168-
Status::Flagship | Status::Accepted | Status::Proposed => true,
169-
Status::NotAccepted => false,
170-
}
166+
self.metadata.status.is_not_not_accepted()
171167
}
172168

173169
/// Modify the goal document on disk to link to the given issue number in the metadata.
@@ -176,9 +172,19 @@ impl GoalDocument {
176172
metadata_table.add_key_value_row(TRACKING_ISSUE_ROW, &number);
177173
self.metadata
178174
.table
175+
179176
.overwrite_in_path(&self.path, &metadata_table)?;
180177
Ok(())
181178
}
179+
180+
/// In goal lists, we render our point-of-contact as "Help Wanted" if this is an invited goal.
181+
pub fn point_of_contact_for_goal_list(&self) -> String {
182+
if self.metadata.status.is_invited {
183+
"![Help Wanted][]".to_string()
184+
} else {
185+
self.metadata.pocs.clone()
186+
}
187+
}
182188
}
183189

184190
/// Format a set of team asks into a table, with asks separated by team and grouped by kind.
@@ -243,7 +249,7 @@ pub fn format_team_asks(asks_of_any_team: &[&TeamAsk]) -> anyhow::Result<String>
243249

244250
pub fn format_goal_table(goals: &[&GoalDocument]) -> anyhow::Result<String> {
245251
// If any of the goals have tracking issues, include those in the table.
246-
let goals_are_proposed = goals.iter().any(|g| g.metadata.status == Status::Proposed);
252+
let goals_are_proposed = goals.iter().any(|g| g.metadata.status.acceptance == AcceptanceStatus::Proposed);
247253

248254
let mut table;
249255

@@ -276,7 +282,7 @@ pub fn format_goal_table(goals: &[&GoalDocument]) -> anyhow::Result<String> {
276282

277283
table.push(vec![
278284
format!("[{}]({})", goal.metadata.title, goal.link_path.display()),
279-
goal.metadata.pocs.clone(),
285+
goal.point_of_contact_for_goal_list(),
280286
progress_bar,
281287
]);
282288
}
@@ -297,7 +303,7 @@ pub fn format_goal_table(goals: &[&GoalDocument]) -> anyhow::Result<String> {
297303
let teams: Vec<&TeamName> = teams.into_iter().collect();
298304
table.push(vec![
299305
format!("[{}]({})", goal.metadata.title, goal.link_path.display()),
300-
goal.metadata.pocs.clone(),
306+
goal.point_of_contact_for_goal_list(),
301307
commas(&teams),
302308
]);
303309
}
@@ -306,38 +312,60 @@ pub fn format_goal_table(goals: &[&GoalDocument]) -> anyhow::Result<String> {
306312
}
307313

308314
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Copy, Clone)]
309-
pub enum Status {
310-
Flagship,
311-
Accepted,
312-
Proposed,
313-
NotAccepted,
315+
pub struct Status {
316+
/// If true, this is a flagship goal (or a flagship candidate)
317+
pub is_flagship: bool,
318+
319+
pub acceptance: AcceptanceStatus,
320+
321+
/// If true, this is an INVITED goal, meaning that it lacks a primary owner
322+
pub is_invited: bool,
323+
}
324+
325+
impl Status {
326+
/// True if this goal has not yet been rejected
327+
pub fn is_not_not_accepted(&self) -> bool {
328+
self.acceptance != AcceptanceStatus::NotAccepted
329+
}
314330
}
315331

316332
impl TryFrom<&str> for Status {
317333
type Error = anyhow::Error;
318334

319335
fn try_from(value: &str) -> anyhow::Result<Self> {
320-
let status_values = &[
321-
("Flagship", Status::Flagship),
322-
("Accepted", Status::Accepted),
323-
("Proposed", Status::Proposed),
324-
("Not accepted", Status::NotAccepted),
336+
let value = value.trim();
337+
338+
let valid_values = [
339+
("Flagship", Status { is_flagship: true, acceptance: AcceptanceStatus::Accepted, is_invited: false }),
340+
("Accepted", Status { is_flagship: false, acceptance: AcceptanceStatus::Accepted, is_invited: false }),
341+
("Invited", Status { is_flagship: false, acceptance: AcceptanceStatus::Accepted, is_invited: true }),
342+
("Proposed", Status { is_flagship: false, acceptance: AcceptanceStatus::Proposed, is_invited: false }),
343+
("Proposed for flagship", Status { is_flagship: true, acceptance: AcceptanceStatus::Proposed, is_invited: true }),
344+
("Proposed for mentorship", Status { is_flagship: false, acceptance: AcceptanceStatus::Proposed, is_invited: true }),
345+
("Not accepted", Status { is_flagship: false, acceptance: AcceptanceStatus::NotAccepted, is_invited: false }),
325346
];
326347

327-
status_values
328-
.iter()
329-
.find(|pair| value == pair.0)
330-
.map(|pair| pair.1)
331-
.ok_or_else(|| {
332-
anyhow::anyhow!(
333-
"unrecognized status `{}`, expected one of: {}",
334-
value,
335-
commas(status_values.iter().map(|pair| pair.0))
336-
)
337-
})
348+
for (valid_value, status) in valid_values {
349+
if value == valid_value {
350+
return Ok(status);
351+
}
352+
}
353+
354+
anyhow::bail!(
355+
"unrecognized status `{}`, expected one of {:?}",
356+
value,
357+
valid_values.iter().map(|(s, _)| s).collect::<Vec<_>>(),
358+
)
338359
}
339360
}
340361

362+
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Copy, Clone)]
363+
pub enum AcceptanceStatus {
364+
Proposed,
365+
Accepted,
366+
NotAccepted,
367+
}
368+
341369
fn extract_metadata(sections: &[Section]) -> anyhow::Result<Option<Metadata>> {
342370
let Some(first_section) = sections.first() else {
343371
anyhow::bail!("no markdown sections found in input")

crates/rust-project-goals/src/re.rs

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,24 @@ lazy_static! {
55
pub static ref TEAM_ASKS: Regex = Regex::new(r"<!-- TEAM ASKS -->").unwrap();
66
}
77

8+
// List of all goals, flagship or otherwise
89
lazy_static! {
9-
pub static ref GOAL_LIST: Regex = Regex::new(r"<!-- GOALS '(.*)' -->").unwrap();
10+
pub static ref GOAL_LIST: Regex = Regex::new(r"<!-- GOALS -->").unwrap();
11+
}
12+
13+
// List of flagship goals (accepted or pending)
14+
lazy_static! {
15+
pub static ref FLAGSHIP_GOAL_LIST: Regex = Regex::new(r"<!-- FLAGSHIP GOALS -->").unwrap();
16+
}
17+
18+
// List of non-flagship goals (accepted or pending)
19+
lazy_static! {
20+
pub static ref OTHER_GOAL_LIST: Regex = Regex::new(r"<!-- OTHER GOALS -->").unwrap();
21+
}
22+
23+
// List of not accepted goals
24+
lazy_static! {
25+
pub static ref GOAL_NOT_ACCEPTED_LIST: Regex = Regex::new(r"<!-- GOALS NOT ACCEPTED -->").unwrap();
1026
}
1127

1228
lazy_static! {

src/2024h2/accepted.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,4 @@ This page lists the project goals accepted for 2024h2, with the exception of [fl
44

55
Some goals here do not yet have an owner (look for the ![Help wanted][] badge). Teams have reserved some capacity to pursue these goals but until an appropriate owner is found they are only considered provisionally accepted. If you are interested in serving as the owner for one of these orphaned goals, reach out to the mentor listed in the goal to discuss.
66

7-
<!-- GOALS 'Accepted' -->
7+
<!-- GOALS -->

src/2024h2/flagship.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
# Flagship goals
22

3-
<!-- GOALS 'Flagship' -->
3+
<!-- FLAGSHIP GOALS -->

src/2024h2/goals.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,12 @@ This page lists the <!-- #GOALS --> project goals accepted for 2024h2.
66

77
Flagship goals represent the goals expected to have the broadest overall impact.
88

9-
<!-- GOALS 'Flagship' -->
9+
<!-- FLAGSHIP GOALS -->
1010

1111
## Other goals
1212

13-
These are the other accepted goals.
13+
This is the full list of goals (including flagship).
1414

15-
**Orphaned goals.** Some goals here are marked with the ![Help wanted][] badge for their owner. These goals are called "orphaned goals". Teams have reserved some capacity to pursue these goals but until an appropriate owner is found they are only considered provisionally accepted. If you are interested in serving as the owner for one of these orphaned goals, reach out to the mentor listed in the goal to discuss.
15+
**Invited goals.** Some goals here are marked with the ![Help wanted][] badge for their point of contact. These goals are called "invited goals". Teams have reserved some capacity to pursue these goals but until an appropriate owner is found they are only considered provisionally accepted. If you are interested in serving as the owner for one of these invited goals, reach out to the point of contact listed in the goal description.
1616

17-
<!-- GOALS 'Accepted' -->
17+
<!-- OTHER GOALS -->

src/2024h2/not_accepted.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,4 @@
22

33
This section contains goals that were proposed but ultimately not accepted, either for want of resources or consensus. In many cases, narrower versions of these goals were accepted.
44

5-
<!-- GOALS 'Not accepted' -->
5+
<!-- GOALS NOT ACCEPTED -->

src/2024h2/user-wide-cache.md

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
# User-wide build cache
22

3-
| Metadata | |
4-
|----------------|------------------------------------|
5-
| Point of contact | @epage |
6-
| Teams | [cargo] |
7-
| Status | Accepted |
8-
| Tracking issue | [rust-lang/rust-project-goals#124] |
3+
| Metadata | |
4+
|------------------|------------------------------------|
5+
| Point of contact | @epage |
6+
| Teams | [cargo] |
7+
| Status | Invited |
8+
| Tracking issue | [rust-lang/rust-project-goals#124] |
99

1010

1111
## Summary

0 commit comments

Comments
 (0)