Skip to content

Commit

Permalink
Permit subteams to have subteams
Browse files Browse the repository at this point in the history
  • Loading branch information
fmease committed Aug 23, 2023
1 parent 8d35e36 commit ac1c25c
Show file tree
Hide file tree
Showing 2 changed files with 36 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
40 changes: 24 additions & 16 deletions src/validate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -161,25 +161,33 @@ 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 `{}` is part of a cycle", parent);
}

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 ac1c25c

Please sign in to comment.