mol-core 0.3.0

Core Libraray for mol crate
Documentation
use std::collections::{HashMap, HashSet};

use crate::changeset::Changeset;
use crate::package::PackageGraph;
use crate::version::{VersionEditor, VersionMod};

#[derive(Debug, Default)]
pub struct Bump<T> {
  changesets: Vec<Changeset<T>>,
  package_update: HashMap<String, VersionMod<T>>,
  package_changesets: HashMap<String, HashSet<usize>>,
}

impl<'a, T: VersionEditor> Bump<T> {
  fn set_package_update(
    package_update: &mut HashMap<String, VersionMod<T>>,
    name: &str,
    version: VersionMod<T>,
  ) {
    if let Some(concat_version) = package_update.get_mut(name) {
      if &version > concat_version {
        *concat_version = version;
      }
    } else {
      package_update.insert(name.to_owned(), version);
    }
  }

  pub fn add(&mut self, changeset: Changeset<T>, graph: &PackageGraph<'_, T>) {
    let min_update = T::options().into_iter().min().unwrap_or_default();
    let index = self.changesets.len();
    self.changesets.insert(index, changeset);
    let changeset = &self.changesets[index];

    for (name, version) in &changeset.packages {
      if let Some(changesets) = self.package_changesets.get_mut(name) {
        changesets.insert(index);
      } else {
        self
          .package_changesets
          .insert(name.clone(), vec![index].into_iter().collect());
      }

      Self::set_package_update(&mut self.package_update, name, version.clone());

      for package in graph.child_changes(name) {
        Self::set_package_update(
          &mut self.package_update,
          &package.name,
          VersionMod::new(min_update.clone()),
        );
      }
    }
  }

  pub fn is_empty(&self) -> bool {
    self.changesets.is_empty()
  }

  pub fn package(&'a self, name: &'a str) -> PackageBump<'a, T> {
    PackageBump { name, bump: self }
  }
}

pub struct PackageBump<'a, T> {
  name: &'a str,
  bump: &'a Bump<T>,
}

impl<'a, T> PackageBump<'a, T> {
  pub fn changesets(&self) -> Option<Vec<&'a Changeset<T>>> {
    self.bump.package_changesets.get(self.name).map(|indexes| {
      indexes
        .iter()
        .map(|index| &self.bump.changesets[*index])
        .collect()
    })
  }

  pub fn name(&self) -> &str {
    self.name
  }

  pub fn version(&self) -> Option<&VersionMod<T>> {
    self.bump.package_update.get(self.name)
  }
}

#[cfg(test)]
mod tests {

  use super::*;
  use crate::prelude::*;

  #[test]
  fn add() {
    let packages = vec![];

    let mut bump = Bump::default();
    let graph = packages.as_package_graph();

    bump.add(
      Changeset {
        packages: vec![("mol".to_owned(), VersionMod::new(Semantic::minor()))]
          .into_iter()
          .collect(),
        message: "Hi".to_owned(),
      },
      &graph,
    );
    bump.add(
      Changeset {
        packages: vec![
          ("mol".to_owned(), VersionMod::new(Semantic::patch())),
          ("mol-core".to_owned(), VersionMod::new(Semantic::major())),
        ]
        .into_iter()
        .collect(),
        message: "Too bad we dont play games".to_owned(),
      },
      &graph,
    );

    assert_eq!(bump.changesets.len(), 2);
    assert_eq!(
      bump.package_changesets.get("mol-core"),
      Some(&vec![1].into_iter().collect())
    );
    assert_eq!(
      bump.package_changesets.get("mol"),
      Some(&vec![0, 1].into_iter().collect())
    );
    assert_eq!(
      bump.package_update.get("mol"),
      Some(&VersionMod::new(Semantic::minor()))
    );
    assert_eq!(
      bump.package_update.get("mol-core"),
      Some(&VersionMod::new(Semantic::major()))
    );
  }

  #[test]
  fn changesets() {
    let packages = vec![];

    let mut bump = Bump::default();
    let graph = packages.as_package_graph();

    bump.add(
      Changeset {
        packages: vec![("mol".to_owned(), VersionMod::new(Semantic::minor()))]
          .into_iter()
          .collect(),
        message: "Hi".to_owned(),
      },
      &graph,
    );
    bump.add(
      Changeset {
        packages: vec![("mol-core".to_owned(), VersionMod::new(Semantic::major()))]
          .into_iter()
          .collect(),
        message: "Too bad we dont play games".to_owned(),
      },
      &graph,
    );

    let changesets = bump.package("mol").changesets();

    assert!(changesets.is_some());

    let changesets = changesets.unwrap();

    assert_eq!(changesets.len(), 1);
    assert_eq!(changesets[0].message, "Hi");

    let changesets = bump.package("mol-core").changesets();

    assert!(changesets.is_some());

    let changesets = changesets.unwrap();

    assert_eq!(changesets.len(), 1);
    assert_eq!(changesets[0].message, "Too bad we dont play games");
  }

  #[test]
  fn dependecy_bump() {
    let packages = vec![
      Package {
        name: "mol-core".to_owned(),
        path: "".into(),
        version: "0.1.0".into(),
        dependencies: vec![],
      },
      Package {
        name: "mol".to_owned(),
        path: "".into(),
        version: "0.1.0".into(),
        dependencies: vec![("mol-core".to_owned(), "0.1".to_owned())],
      },
      Package {
        name: "mol-cargo".to_owned(),
        path: "".into(),
        version: "0.1.0".into(),
        dependencies: vec![("mol-core".to_owned(), "0.1".to_owned())],
      },
    ];

    let mut bump = Bump::default();
    let graph = packages.as_package_graph();

    bump.add(
      Changeset {
        packages: vec![("mol-core".to_owned(), VersionMod::new(Semantic::minor()))]
          .into_iter()
          .collect(),
        message: "Too bad we dont play games".to_owned(),
      },
      &graph,
    );

    assert_eq!(
      bump.package_update,
      vec![
        ("mol-core".to_owned(), VersionMod::new(Semantic::minor())),
        ("mol".to_owned(), VersionMod::new(Semantic::patch())),
        ("mol-cargo".to_owned(), VersionMod::new(Semantic::patch()))
      ]
      .into_iter()
      .collect()
    );
  }
}