Skip to content

Commit 538e041

Browse files
authored
Merge pull request rust-lang#1046 from fmease/subsubteams
Permit subteams to have subteams
2 parents 257fb85 + 5c92cbf commit 538e041

File tree

2 files changed

+39
-18
lines changed

2 files changed

+39
-18
lines changed

src/schema.rs

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -186,10 +186,11 @@ impl Team {
186186

187187
// Return's whether the provided team is a subteam of this team
188188
pub(crate) fn is_parent_of<'a>(&'a self, data: &'a Data, subteam: &Team) -> bool {
189+
let mut visited = Vec::new();
189190
let mut subteam = Some(subteam);
190-
while let Some(s) = subteam {
191+
while let Some(team) = subteam {
191192
// Get subteam's parent
192-
let Some(parent) = s.subteam_of() else {
193+
let Some(parent) = team.subteam_of() else {
193194
// The current subteam is a top level team.
194195
// Therefore this team cannot be its parent.
195196
return false;
@@ -198,7 +199,16 @@ impl Team {
198199
if parent == self.name {
199200
return true;
200201
}
202+
203+
visited.push(team.name.as_str());
204+
201205
// Otherwise try the test again with the parent
206+
// unless we have already visited it.
207+
208+
if visited.contains(&parent) {
209+
// We have found a cycle, give up.
210+
return false;
211+
}
202212
subteam = data.team(parent);
203213
}
204214
false

src/validate.rs

Lines changed: 27 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -161,25 +161,36 @@ fn validate_name_prefixes(data: &Data, errors: &mut Vec<String>) {
161161

162162
/// Ensure `subteam-of` points to an existing team
163163
fn validate_subteam_of(data: &Data, errors: &mut Vec<String>) {
164-
let teams: HashMap<_, _> = data
165-
.teams()
166-
.map(|t| (t.name(), t.subteam_of().is_some()))
167-
.collect();
168-
wrapper(data.teams(), errors, |team, _| {
169-
if let Some(subteam_of) = team.subteam_of() {
170-
match teams.get(subteam_of) {
171-
Some(false) => {}
172-
Some(true) => bail!(
173-
"team `{}` can't be a subteam of a subteam (`{}`)",
174-
team.name(),
175-
subteam_of
176-
),
177-
None => bail!(
164+
wrapper(data.teams(), errors, |mut team, _| {
165+
let mut visited = Vec::new();
166+
while let Some(parent) = team.subteam_of() {
167+
visited.push(team.name());
168+
169+
if visited.contains(&parent) {
170+
bail!(
171+
"team `{parent}` is a subteam of itself: {} => {parent}",
172+
visited.join(" => "),
173+
);
174+
}
175+
176+
let Some(parent) = data.team(parent) else {
177+
bail!(
178178
"the parent of team `{}` doesn't exist: `{}`",
179179
team.name(),
180-
subteam_of
181-
),
180+
parent,
181+
);
182+
};
183+
184+
if !matches!(team.kind(), TeamKind::Team) && parent.subteam_of().is_some() {
185+
bail!(
186+
"{} `{}` can't be a subteam of a subteam (`{}`)",
187+
team.kind(),
188+
team.name(),
189+
parent.name(),
190+
);
182191
}
192+
193+
team = parent;
183194
}
184195
Ok(())
185196
});

0 commit comments

Comments
 (0)