Skip to content

Commit

Permalink
Merge pull request #1046 from fmease/subsubteams
Browse files Browse the repository at this point in the history
Permit subteams to have subteams
  • Loading branch information
rylev authored Aug 28, 2023
2 parents 257fb85 + 5c92cbf commit 538e041
Show file tree
Hide file tree
Showing 2 changed files with 39 additions and 18 deletions.
14 changes: 12 additions & 2 deletions src/schema.rs
Original file line number Diff line number Diff line change
Expand Up @@ -186,10 +186,11 @@ impl Team {

// Return's whether the provided team is a subteam of this team
pub(crate) fn is_parent_of<'a>(&'a self, data: &'a Data, subteam: &Team) -> bool {
let mut visited = Vec::new();
let mut subteam = Some(subteam);
while let Some(s) = subteam {
while let Some(team) = subteam {
// Get subteam's parent
let Some(parent) = s.subteam_of() else {
let Some(parent) = team.subteam_of() else {
// The current subteam is a top level team.
// Therefore this team cannot be its parent.
return false;
Expand All @@ -198,7 +199,16 @@ impl Team {
if parent == self.name {
return true;
}

visited.push(team.name.as_str());

// Otherwise try the test again with the parent
// unless we have already visited it.

if visited.contains(&parent) {
// We have found a cycle, give up.
return false;
}
subteam = data.team(parent);
}
false
Expand Down
43 changes: 27 additions & 16 deletions src/validate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -161,25 +161,36 @@ fn validate_name_prefixes(data: &Data, errors: &mut Vec<String>) {

/// Ensure `subteam-of` points to an existing team
fn validate_subteam_of(data: &Data, errors: &mut Vec<String>) {
let teams: HashMap<_, _> = data
.teams()
.map(|t| (t.name(), t.subteam_of().is_some()))
.collect();
wrapper(data.teams(), errors, |team, _| {
if let Some(subteam_of) = team.subteam_of() {
match teams.get(subteam_of) {
Some(false) => {}
Some(true) => bail!(
"team `{}` can't be a subteam of a subteam (`{}`)",
team.name(),
subteam_of
),
None => bail!(
wrapper(data.teams(), errors, |mut team, _| {
let mut visited = Vec::new();
while let Some(parent) = team.subteam_of() {
visited.push(team.name());

if visited.contains(&parent) {
bail!(
"team `{parent}` is a subteam of itself: {} => {parent}",
visited.join(" => "),
);
}

let Some(parent) = data.team(parent) else {
bail!(
"the parent of team `{}` doesn't exist: `{}`",
team.name(),
subteam_of
),
parent,
);
};

if !matches!(team.kind(), TeamKind::Team) && parent.subteam_of().is_some() {
bail!(
"{} `{}` can't be a subteam of a subteam (`{}`)",
team.kind(),
team.name(),
parent.name(),
);
}

team = parent;
}
Ok(())
});
Expand Down

0 comments on commit 538e041

Please sign in to comment.