Skip to content

Commit

Permalink
feat: --exclude argument for anda update
Browse files Browse the repository at this point in the history
  • Loading branch information
madonuko committed Jul 25, 2024
1 parent 40b4b90 commit f9f40a0
Show file tree
Hide file tree
Showing 4 changed files with 40 additions and 10 deletions.
5 changes: 4 additions & 1 deletion anda-config/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -203,8 +203,11 @@ pub fn parse_kv(input: &str) -> impl Iterator<Item = Option<(String, String)>> +
.map(|item| item.split_once('=').map(|(l, r)| (l.to_owned(), r.to_owned())))
}

pub fn parse_filters(filters: &[String]) -> Option<Vec<Vec<(String, String)>>> {
filters.iter().map(std::ops::Deref::deref).map(crate::parse_kv).map(Iterator::collect).collect()
}

/// Turn a string into a BTreeMap<String, String>
#[must_use]
pub fn parse_labels<'a, I: Iterator<Item = &'a str>>(labels: I) -> Option<Vec<(String, String)>> {
labels.flat_map(parse_kv).collect()
}
Expand Down
21 changes: 21 additions & 0 deletions src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -193,8 +193,29 @@ pub enum Command {
#[clap(short, long)]
labels: Vec<String>,
/// Only run update scripts in project with the specified labels
///
/// This should be a comma-separated list of filters.
/// Each time `--filters=...` is specified, the comma-separated list of key-values will be
/// checked against a project. If missing or different, the project will be ignored.
/// However, specifying `--filters` multiple times will create an "or" effect --- the
/// project will not be ignored if it satisfies one of the list of `--filters`. For
/// example, `-f a=1,b=2 -f c=3` means the project needs to satisfy either "a=1" and "b=2",
/// or only "c=3".
#[clap(short, long)]
filters: Vec<String>,
/// Exclude update scripts in project with the specified labels
///
/// This should be a comma-separated list of excludes.
/// Each time `--exclude=...` is specified, the comma-separated list of key-values will be
/// checked against the labels of a project, and it will be ignored if all the key-values
/// are present. In addition, specifying `--exclude` multiple times will create an "or"
/// effect --- a project will be excluded if it satisfies one of the list of `--filters`.
/// For example, `-e a=1,b=2 -e c=3` means projects with "a=1" and "b=2" at the same time,
/// or "c=3", are excluded. Projects with only "a=1" or "b=2" are not excluded.
///
/// This will always override `--filters`.
#[clap(short, long)]
excludes: Vec<String>,
},

/// Run .rhai scripts
Expand Down
13 changes: 5 additions & 8 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -102,17 +102,14 @@ async fn main() -> Result<()> {

println!("build_matrix={}", serde_json::to_string(&entries)?);
}
Command::Update { labels, filters } => {
Command::Update { labels, filters, excludes } => {
let labels = parse_labels(labels.iter().map(std::ops::Deref::deref))
.ok_or_else(|| eyre!("Cannot parse --labels"))?;
let filters = filters
.iter()
.map(std::ops::Deref::deref)
.map(anda_config::parse_kv)
.map(Iterator::collect)
.collect::<Option<_>>()
let filters = anda_config::parse_filters(&filters)
.ok_or_else(|| eyre!("Cannot parse --filters"))?;
update::update(anda_config::load_from_file(&cli.config)?, labels, filters)?;
let excludes = anda_config::parse_filters(&excludes)
.ok_or_else(|| eyre!("Cannot parse --excludes"))?;
update::update(anda_config::load_from_file(&cli.config)?, labels, filters, excludes)?;
}
Command::Run { scripts, labels } => {
if scripts.is_empty() {
Expand Down
11 changes: 10 additions & 1 deletion src/update.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,22 @@ use std::{
use tracing::{debug, error, instrument, trace};

/// Return true only if the project `lbls` does not have the key or the value does not match.
fn filter_project(lbls: &BTreeMap<String, String>) -> impl FnMut(&(String, String)) -> bool + '_ {
fn filter_project(lbls: &BTreeMap<String, String>) -> impl Fn(&(String, String)) -> bool + '_ {
|(k, v)| lbls.get(k).map_or(true, |val| val != v)
}

/// Return true only if `lbls` have the key and the value matches.
fn exclude_project(lbls: &BTreeMap<String, String>) -> impl Fn(&(String, String)) -> bool + '_ {
|(k, v)| lbls.get(k).is_some_and(|val| val == v)
}

#[allow(clippy::arithmetic_side_effects)]
#[instrument(skip(cfg))]
pub fn update(
cfg: Manifest,
global_lbls: Vec<(String, String)>,
fls: Vec<Vec<(String, String)>>,
excls: Vec<Vec<(String, String)>>,
) -> Result<()> {
let mut handlers = vec![];
let proj_len = cfg.project.len();
Expand All @@ -32,6 +38,9 @@ pub fn update(
if fls.iter().all(|fls| fls.iter().any(filter_project(&lbls))) {
continue;
}
if excls.iter().any(|excls| excls.iter().all(exclude_project(&lbls))) {
continue;
}
trace!(name, scr = scr.to_str(), "Th start");
let fls = fls.clone();
let alias = proj.alias.into_iter().flatten().next().clone().unwrap_or(name);
Expand Down

0 comments on commit f9f40a0

Please sign in to comment.