use chrono::{DateTime, Duration, Local};
use itertools::Itertools;
use super::{Options, VersionedSource};
use crate::sources::list::Tag;
#[allow(dead_code)]
pub fn process_result(sources: &[VersionedSource], options: &Options) -> Vec<VersionedSource> {
let since = compute_since_date(options);
sources
.iter()
.filter_map(|source| process_versioned_source(source, since))
.collect::<Vec<VersionedSource>>()
}
pub fn compute_since_date(options: &Options) -> DateTime<Local> {
let now = Local::now();
match (options.since, options.last) {
(None, None) => now - Duration::days(1),
(None, Some(duration)) => {
now - Duration::from_std(duration).unwrap_or_else(|_| Duration::days(365 * 100))
}
(Some(since), _) => since,
}
}
fn process_versioned_source(
source: &VersionedSource,
since: DateTime<Local>,
) -> Option<VersionedSource> {
let versions_filtered: Vec<Tag> = source
.versions
.iter()
.filter_map(|tag| tag.created_at().map(|created_at| (tag, created_at)))
.filter(|(_, created_at)| **created_at > since)
.sorted_by(|(_, created_at_a), (_, created_at_b)| Ord::cmp(created_at_b, created_at_a))
.map(|(tag, _)| tag.clone())
.collect();
if versions_filtered.is_empty() {
None
} else {
Some(VersionedSource {
source: source.source.clone(),
versions: versions_filtered,
})
}
}
#[cfg(test)]
mod test {
use chrono::{Duration, Local};
use super::super::{Source, VersionedSource};
fn mock1() -> VersionedSource {
VersionedSource {
source: Source {
label: None,
source: "git+https://github.com/foo/bar#tag=v1.2".parse().unwrap(),
include: None,
exclude: None,
},
versions: vec![
tag!("2.0.1").with_created_at(chrono::Local::now()),
tag!("1.0.0").with_created_at(chrono::Local::now() - chrono::Duration::days(2)),
tag!("2.0.0").with_created_at(chrono::Local::now() - chrono::Duration::hours(2)),
tag!("0.1.0").with_created_at(chrono::Local::now() - chrono::Duration::weeks(2)),
],
}
}
fn mock2() -> VersionedSource {
VersionedSource {
source: Source {
label: Some("adnv cli".to_string()),
source: "git+https://gitlab.com/adnap/tools/adnv".parse().unwrap(),
include: None,
exclude: None,
},
versions: vec![
tag!("1.0.0").with_created_at(chrono::Local::now() - chrono::Duration::weeks(1)),
],
}
}
#[test]
fn test_succeeds_without_options() {
let mock1 = mock1();
let mock2 = mock2();
let sources = vec![mock1.clone(), mock2];
let result = super::process_result(
&sources,
&super::Options {
last: None,
since: None,
include: None,
exclude: None,
outputs: vec![],
},
);
let wanted = vec![VersionedSource {
source: mock1.source,
versions: vec![mock1.versions[0].clone(), mock1.versions[2].clone()],
}];
pretty_assertions::assert_eq!(wanted, result);
}
#[test]
fn test_succeeds_with_last_10_days_ago() {
let mock1 = mock1();
let mock2 = mock2();
let sources = [mock1.clone(), mock2.clone()];
let result = super::process_result(
&sources,
&super::Options {
last: Some(Duration::days(10).to_std().unwrap()),
since: None,
include: None,
exclude: None,
outputs: vec![],
},
);
let wanted = vec![
VersionedSource {
source: mock1.source,
versions: vec![
mock1.versions[0].clone(),
mock1.versions[2].clone(),
mock1.versions[1].clone(),
],
},
VersionedSource {
source: mock2.source,
versions: vec![mock2.versions[0].clone()],
},
];
pretty_assertions::assert_eq!(wanted, result);
}
#[test]
fn test_succeeds_with_since_3_weeks_ago() {
let mock1 = mock1();
let mock2 = mock2();
let sources = [mock1.clone(), mock2.clone()];
let result = super::process_result(
&sources,
&super::Options {
last: None,
since: Some(Local::now() - Duration::weeks(3)),
include: None,
exclude: None,
outputs: vec![],
},
);
let wanted = vec![
VersionedSource {
source: mock1.source,
versions: vec![
mock1.versions[0].clone(),
mock1.versions[2].clone(),
mock1.versions[1].clone(),
mock1.versions[3].clone(),
],
},
mock2,
];
pretty_assertions::assert_eq!(wanted, result);
}
}