use crate::Result;
use crate::sources::resolve::ResolvedSource;
pub fn apply<'a>(sources: impl IntoIterator<Item = &'a ResolvedSource>) -> Result<()> {
use itertools::Itertools;
use crate::util::edit;
for (path, sources) in &sources
.into_iter()
.sorted_by_key(|source| source.source.source.location().unwrap().path())
.chunk_by(|source| source.source.source.location().unwrap().path())
{
let actions: Vec<_> = sources
.filter(|source| source.wanted.is_some())
.filter_map(|source| {
Some((
source.source.source.location().unwrap().span()?,
&source.wanted,
))
})
.map(|((start, end), version)| {
edit::Action::replace(start..=end, format!("\"{}\"", version.as_ref().unwrap()))
})
.collect();
edit::edit_file(path, &actions)?;
}
Ok(())
}
#[cfg(test)]
mod tests {
use super::apply;
use crate::sources::parse::{Location, ParseOptions, parse_dir};
use crate::sources::resolve::ResolvedSource;
#[tokio::test]
async fn parsed_spans_land_on_the_versions_they_describe() {
let dir = tempfile::TempDir::with_prefix("adnv-apply").unwrap();
let terraform = "\
# Déploiement du namespace à créer
module \"namespace\" {
source = \"gitlab.com/vigigloo/tf-modules/k8slimitednamespace\"
version = \"0.3.5\"
}
# Référence : le module précédent, déjà à jour
module \"mattermost\" {
source = \"gitlab.com/vigigloo/tools-k8s/mattermost\"
version = \"0.1.0\"
}
";
let chart = "\
apiVersion: v2
name: déploiement
version: 1.0.0
dependencies:
# Révision à suivre
- name: nginx-ingress
version: \"0.17.0\"
repository: \"https://helm.nginx.com/stable\"
";
std::fs::write(dir.path().join("main.tf"), terraform).unwrap();
std::fs::write(dir.path().join("Chart.yaml"), chart).unwrap();
let (parsed, errors) = parse_dir(
dir.path(),
&ParseOptions {
recursive: false,
hidden: false,
},
)
.await
.split();
assert!(errors.is_empty(), "{errors:?}");
assert_eq!(parsed.len(), 3, "{parsed:?}");
let resolved: Vec<_> = parsed
.into_iter()
.map(|source| {
let location = source.source.location().unwrap();
let (line, col) = location.loc();
let (start, end) = location.span().unwrap();
let rebased = Location::new(dir.path().join(location.path()), line, col)
.with_span(start, end);
ResolvedSource::new(source.with_location(rebased), "9.9.9").with_wanted("9.9.9")
})
.collect();
apply(&resolved).expect("every span describes the file it came from");
assert_eq!(
std::fs::read_to_string(dir.path().join("main.tf")).unwrap(),
terraform
.replace("\"0.3.5\"", "\"9.9.9\"")
.replace("\"0.1.0\"", "\"9.9.9\"")
);
assert_eq!(
std::fs::read_to_string(dir.path().join("Chart.yaml")).unwrap(),
chart.replace("\"0.17.0\"", "\"9.9.9\"")
);
}
}