From f0079de5580831fee0b75bbd28e514b34298707e Mon Sep 17 00:00:00 2001 From: codcod Date: Thu, 6 Nov 2025 07:22:27 +0100 Subject: [PATCH] feat: use AND not OR to filter repos --- src/config/loader.rs | 6 +++--- src/utils/filters.rs | 38 +++++++++++++++++++++++++++++++++----- 2 files changed, 36 insertions(+), 8 deletions(-) diff --git a/src/config/loader.rs b/src/config/loader.rs index 2824775..19fc816 100644 --- a/src/config/loader.rs +++ b/src/config/loader.rs @@ -573,11 +573,11 @@ mod tests { // Test include and exclude together let filtered = config.filter_repositories( - &["web".to_string(), "api".to_string()], // include web OR api - &["frontend".to_string()], // but exclude frontend + &["backend".to_string(), "api".to_string()], // include backend AND api (only repo2 has both) + &["frontend".to_string()], // but exclude frontend None, ); assert_eq!(filtered.len(), 1); - assert_eq!(filtered[0].name, "repo2"); // repo2 has api but not frontend + assert_eq!(filtered[0].name, "repo2"); // repo2 has backend AND api, not frontend } } diff --git a/src/utils/filters.rs b/src/utils/filters.rs index 90f7366..90ce3a0 100644 --- a/src/utils/filters.rs +++ b/src/utils/filters.rs @@ -72,9 +72,9 @@ pub fn filter_repositories( base_repos .into_iter() .filter(|repo| { - // Check inclusion filter: if include_tags is empty, include all; otherwise check if repo has any included tag + // Check inclusion filter: if include_tags is empty, include all; otherwise check if repo has all included tags (AND logic) let included = - include_tags.is_empty() || include_tags.iter().any(|tag| repo.has_tag(tag)); + include_tags.is_empty() || include_tags.iter().all(|tag| repo.has_tag(tag)); // Check exclusion filter: if exclude_tags is empty, exclude none; otherwise check if repo has any excluded tag let excluded = @@ -212,12 +212,12 @@ mod tests { // Test include and exclude together let filtered = filter_repositories( &repos, - &["web".to_string(), "api".to_string()], // include web OR api - &["frontend".to_string()], // but exclude frontend + &["web".to_string(), "frontend".to_string()], // include web AND frontend (only repo1 has both) + &["backend".to_string()], // but exclude backend None, ); assert_eq!(filtered.len(), 1); - assert_eq!(filtered[0].name, "repo2"); // repo2 has api but not frontend + assert_eq!(filtered[0].name, "repo1"); // repo1 has web AND frontend, not backend } #[test] @@ -237,4 +237,32 @@ mod tests { assert_eq!(filtered.len(), 1); assert_eq!(filtered[0].name, "repo1"); } + + #[test] + fn test_filter_repositories_and_logic_with_multiple_tags() { + let repos = create_test_repositories(); + + // Multiple tags should use AND logic - all tags must be present + let filtered = filter_repositories( + &repos, + &["frontend".to_string(), "web".to_string()], // both tags required + &[], + None, + ); + assert_eq!(filtered.len(), 1); + assert_eq!(filtered[0].name, "repo1"); // Only repo1 has both tags + + // If one tag doesn't exist, no repos should match + let filtered = filter_repositories( + &repos, + &["frontend".to_string(), "nonexistent".to_string()], + &[], + None, + ); + assert_eq!(filtered.len(), 0); + + // Single nonexistent tag should return no repos + let filtered = filter_repositories(&repos, &["nonexistent".to_string()], &[], None); + assert_eq!(filtered.len(), 0); + } }