Skip to content

Commit 201e079

Browse files
committed
Add validation for duplicate team entries
- Add explicit_leads() method to expose team leads - Check leads, members, and alumni for duplicates - Collect all errors for better developer experience
1 parent 9702594 commit 201e079

File tree

2 files changed

+55
-21
lines changed

2 files changed

+55
-21
lines changed

src/schema.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -516,6 +516,10 @@ impl Team {
516516
pub(crate) fn explicit_alumni(&self) -> &[TeamMember] {
517517
self.people.alumni.as_ref().map_or(&[], Vec::as_slice)
518518
}
519+
520+
pub(crate) fn explicit_leads(&self) -> &[String] {
521+
&self.people.leads
522+
}
519523

520524
pub(crate) fn contains_person(&self, data: &Data, person: &Person) -> Result<bool, Error> {
521525
let members = self.members(data)?;

src/validate.rs

Lines changed: 51 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -237,31 +237,61 @@ fn validate_team_members(data: &Data, errors: &mut Vec<String>) {
237237
});
238238
}
239239

240-
/// Ensure no duplicate entries in team members or alumni
240+
/// Helper for checking duplicates in a list
241+
fn check_duplicates<'a, I>(team_name: &str, label: &str, items: I) -> Result<(), Error>
242+
where
243+
I: IntoIterator<Item = &'a str>,
244+
{
245+
let mut seen = HashSet::new();
246+
let mut duplicates = HashSet::new();
247+
248+
for item in items {
249+
if !seen.insert(item) {
250+
duplicates.insert(item);
251+
}
252+
}
253+
254+
if !duplicates.is_empty() {
255+
let dup_list: Vec<&str> = duplicates.into_iter().collect();
256+
bail!(
257+
"team `{}` has duplicate {}: {}",
258+
team_name,
259+
label,
260+
dup_list.join(", ")
261+
);
262+
}
263+
264+
Ok(())
265+
}
266+
267+
/// Ensure no duplicate entries in team leads, members and alumni
241268
fn validate_duplicate_team_entries(data: &Data, errors: &mut Vec<String>) {
242269
wrapper(data.teams(), errors, |team, errors| {
243-
// Check for duplicate members
244-
let mut seen_members = HashSet::new();
245-
for member in team.explicit_members() {
246-
if !seen_members.insert(&member.github) {
247-
errors.push(format!(
248-
"team `{}` has duplicate members: {}",
249-
team.name(),
250-
member.github
251-
));
252-
}
270+
// Check leads for duplicates
271+
if let Err(e) = check_duplicates(
272+
team.name(),
273+
"leads",
274+
team.explicit_leads().iter().map(|s| s.as_str()),
275+
) {
276+
errors.push(e.to_string());
253277
}
254278

255-
// Check for duplicate alumni
256-
let mut seen_alumni = HashSet::new();
257-
for alum in team.explicit_alumni() {
258-
if !seen_alumni.insert(&alum.github) {
259-
errors.push(format!(
260-
"team `{}` has duplicate alumni: {}",
261-
team.name(),
262-
alum.github
263-
));
264-
}
279+
// Check members for duplicates
280+
if let Err(e) = check_duplicates(
281+
team.name(),
282+
"members",
283+
team.explicit_members().iter().map(|m| m.github.as_str()),
284+
) {
285+
errors.push(e.to_string());
286+
}
287+
288+
// Check alumni for duplicates
289+
if let Err(e) = check_duplicates(
290+
team.name(),
291+
"alumni",
292+
team.explicit_alumni().iter().map(|a| a.github.as_str()),
293+
) {
294+
errors.push(e.to_string());
265295
}
266296

267297
Ok(())

0 commit comments

Comments
 (0)