diff options
Diffstat (limited to 'src/commands')
-rw-r--r-- | src/commands/db.rs | 41 | ||||
-rw-r--r-- | src/commands/endpoint.rs | 32 | ||||
-rw-r--r-- | src/commands/util.rs | 33 |
3 files changed, 79 insertions, 27 deletions
diff --git a/src/commands/db.rs b/src/commands/db.rs index 5b9a85a..2e86954 100644 --- a/src/commands/db.rs +++ b/src/commands/db.rs @@ -14,6 +14,7 @@ use std::io::Write; use std::path::PathBuf; use std::process::Command; use std::str::FromStr; +use std::convert::TryFrom; use anyhow::Context; use anyhow::Error; @@ -32,9 +33,11 @@ use log::info; use log::trace; use crate::config::Configuration; -use crate::db::models; use crate::db::DbConnectionConfig; +use crate::db::models; use crate::log::JobResult; +use crate::package::PackageVersion; +use crate::package::PackageVersionConstraint; use crate::package::Script; use crate::schema; @@ -691,7 +694,7 @@ fn releases(conn_cfg: DbConnectionConfig<'_>, config: &Configuration, matches: & let csv = matches.is_present("csv"); let conn = conn_cfg.establish_connection()?; let header = crate::commands::util::mk_header(["Package", "Version", "Date", "Path"].to_vec()); - let data = schema::jobs::table + let mut query = schema::jobs::table .inner_join(schema::packages::table) .inner_join(schema::artifacts::table) .inner_join(schema::releases::table @@ -701,6 +704,28 @@ fn releases(conn_cfg: DbConnectionConfig<'_>, config: &Configuration, matches: & .order_by(schema::packages::dsl::name.asc()) .then_order_by(schema::packages::dsl::version.asc()) .then_order_by(schema::releases::release_date.asc()) + .into_boxed(); + + if let Some(date) = crate::commands::util::get_date_filter("older_than", matches)? { + query = query.filter(schema::releases::release_date.lt(date)); + } + + if let Some(date) = crate::commands::util::get_date_filter("newer_than", matches)? { + query = query.filter(schema::releases::release_date.gt(date)); + } + + let package_name_regex_filter = matches.value_of("package_name_regex") + .map(crate::commands::util::mk_package_name_regex) + .transpose() + .context("Constructing package name regex")?; + + let package_version_filter = matches.value_of("package_version_constraint") + .map(PackageVersionConstraint::try_from) + .transpose() + .context("Parsing package version constraint") + .context("A valid package version constraint looks like this: '=1.0.0'")?; + + let data = query .select({ let art = schema::artifacts::all_columns; let pac = schema::packages::all_columns; @@ -710,8 +735,18 @@ fn releases(conn_cfg: DbConnectionConfig<'_>, config: &Configuration, matches: & }) .load::<(models::Artifact, models::Package, models::Release, models::ReleaseStore)>(&conn)? .into_iter() + .filter(|(_, package, _, _)| { + package_name_regex_filter.as_ref() + .map(|regex| regex.captures(&package.name).is_some()) + .unwrap_or(true) + }) + .filter(|(_, package, _, _)| { + package_version_filter.as_ref() + .map(|verf| verf.matches(&PackageVersion::from(package.version.clone()))) + .unwrap_or(true) + }) .filter_map(|(art, pack, rel, rstore)| { - let p = config.releases_directory().join(rstore.store_name).join(&art.path); + let p = config.releases_directory().join(rstore.store_name).join(&art.path); if p.is_file() { Some(vec![ diff --git a/src/commands/endpoint.rs b/src/commands/endpoint.rs index 4de51d2..6fd7d69 100644 --- a/src/commands/endpoint.rs +++ b/src/commands/endpoint.rs @@ -182,8 +182,8 @@ async fn containers_list(endpoint_names: Vec<EndpointName>, ) -> Result<()> { let list_stopped = matches.is_present("list_stopped"); let filter_image = matches.value_of("filter_image"); - let older_than_filter = get_date_filter("older_than", matches)?; - let newer_than_filter = get_date_filter("newer_than", matches)?; + let older_than_filter = crate::commands::util::get_date_filter("older_than", matches)?; + let newer_than_filter = crate::commands::util::get_date_filter("newer_than", matches)?; let csv = matches.is_present("csv"); let hdr = crate::commands::util::mk_header([ "Endpoint", @@ -232,8 +232,8 @@ async fn containers_prune(endpoint_names: Vec<EndpointName>, matches: &ArgMatches, config: &Configuration, ) -> Result<()> { - let older_than_filter = get_date_filter("older_than", matches)?; - let newer_than_filter = get_date_filter("newer_than", matches)?; + let older_than_filter = crate::commands::util::get_date_filter("older_than", matches)?; + let newer_than_filter = crate::commands::util::get_date_filter("newer_than", matches)?; let stats = connect_to_endpoints(config, &endpoint_names) .await? @@ -279,8 +279,8 @@ async fn containers_top(endpoint_names: Vec<EndpointName>, config: &Configuration, ) -> Result<()> { let limit = matches.value_of("limit").map(usize::from_str).transpose()?; - let older_than_filter = get_date_filter("older_than", matches)?; - let newer_than_filter = get_date_filter("newer_than", matches)?; + let older_than_filter = crate::commands::util::get_date_filter("older_than", matches)?; + let newer_than_filter = crate::commands::util::get_date_filter("newer_than", matches)?; let csv = matches.is_present("csv"); let data = connect_to_endpoints(config, &endpoint_names) @@ -374,8 +374,8 @@ async fn containers_stop(endpoint_names: Vec<EndpointName>, matches: &ArgMatches, config: &Configuration, ) -> Result<()> { - let older_than_filter = get_date_filter("older_than", matches)?; - let newer_than_filter = get_date_filter("newer_than", matches)?; + let older_than_filter = crate::commands::util::get_date_filter("older_than", matches)?; + let newer_than_filter = crate::commands::util::get_date_filter("newer_than", matches)?; let stop_timeout = matches.value_of("timeout") .map(u64::from_str) @@ -422,22 +422,6 @@ async fn containers_stop(endpoint_names: Vec<EndpointName>, } -fn get_date_filter(name: &str, matches: &ArgMatches) -> Result<Option<chrono::DateTime::<chrono::Local>>> { - matches.value_of(name) - .map(humantime::parse_duration) - .transpose()? - .map(chrono::Duration::from_std) - .transpose()? - .map(|dur| { - chrono::offset::Local::now() - .checked_sub_signed(dur) - .ok_or_else(|| anyhow!("Time calculation would overflow")) - .with_context(|| anyhow!("Cannot subtract {} from 'now'", dur)) - .map_err(Error::from) - }) - .transpose() -} - /// Helper function to connect to all endpoints from the configuration, that appear (by name) in /// the `endpoint_names` list pub(super) async fn connect_to_endpoints(config: &Configuration, endpoint_names: &[EndpointName]) -> Result<Vec<Arc<Endpoint>>> { diff --git a/src/commands/util.rs b/src/commands/util.rs index e892875..acfbdd2 100644 --- a/src/commands/util.rs +++ b/src/commands/util.rs @@ -225,3 +225,36 @@ pub fn display_data<D: Display>( } } +pub fn get_date_filter(name: &str, matches: &ArgMatches) -> Result<Option<chrono::DateTime::<chrono::Local>>> { + matches.value_of(name) + .map(|s| { + trace!("Parsing duration: '{}'", s); + humantime::parse_duration(s) + .map_err(Error::from) + .or_else(|_| { + trace!("Parsing time: '{}'", s); + humantime::parse_rfc3339_weak(s) + .map_err(Error::from) + .and_then(|d| d.elapsed().map_err(Error::from)) + }) + .or_else(|_| { + let s = format!("{} 00:00:00", s); + trace!("Parsing time: '{}'", s); + humantime::parse_rfc3339_weak(&s) + .map_err(Error::from) + .and_then(|d| d.elapsed().map_err(Error::from)) + }) + }) + .transpose()? + .map(chrono::Duration::from_std) + .transpose()? + .map(|dur| { + chrono::offset::Local::now() + .checked_sub_signed(dur) + .ok_or_else(|| anyhow!("Time calculation would overflow")) + .with_context(|| anyhow!("Cannot subtract {} from 'now'", dur)) + .map_err(Error::from) + }) + .transpose() +} + |