mfgames-conventional-commit-rs/src/trees.rs

110 lines
3.3 KiB
Rust

use std::cmp::Ordering;
use anyhow::Result;
use git2::{Commit, DiffOptions, Repository};
use slog::{debug, Logger};
use wax::{Any, Pattern};
use crate::{config::PackageSettings, versions::VersionBump};
pub fn get_tree_skip(
log: Logger,
repo: &Repository,
commit: &Commit,
commit_bump: &VersionBump,
package: &PackageSettings,
) -> Result<bool> {
// If we aren't bumping, then there is no reason to check.
if commit_bump == &VersionBump::None {
debug!(log, "tree exclude: no version bump, skipping tree");
return Ok(true);
}
// Get the tree.
let commit_tree = commit.tree()?;
debug!(log, "checking tree {:?}", &commit_tree.id());
// Create the match operations based on the settings. We use the UUID as a
// hihgly unlikely match.
let include = &package.clone().paths.and_then(|v| v.include);
let include = create_match_list(include, "**/*")?;
let never = "75f56059-a95d-4ca4-b8cc-97934b27f3c2";
let exclude = &package.clone().paths.and_then(|v| v.exclude);
let exclude = create_match_list(exclude, never)?;
// Go through the parents so we can get a difference.
for parent in commit.parent_ids() {
// Get the parent information.
let parent_commit = &repo.find_commit(parent)?;
let parent_tree = parent_commit.tree()?;
// Get the difference with the parents.
let mut opts = DiffOptions::new();
let diff = repo.diff_tree_to_tree(
Some(&commit_tree),
Some(&parent_tree),
Some(&mut opts),
)?;
let deltas = diff.deltas();
for delta in deltas {
let old_file_path = delta.old_file().path().unwrap();
let new_file_path = delta.new_file().path().unwrap();
let old_include = include.is_match(old_file_path);
let old_exclude = exclude.is_match(old_file_path);
let new_include = include.is_match(new_file_path);
let new_exclude = exclude.is_match(new_file_path);
let old_match = old_include && !old_exclude;
let new_match = new_include && !new_exclude;
let either_match = old_match || new_match;
if either_match {
debug!(
log,
"tree include: new file {:?} include {:?} exclude {:?}",
new_file_path,
new_include,
new_exclude
);
if new_file_path.cmp(old_file_path) == Ordering::Equal {
debug!(
log,
"tree include: new file {:?} include {:?} exclude {:?}",
new_file_path,
new_include,
new_exclude
);
}
return Ok(false);
}
}
}
// We are going to skip this commit.
debug!(log, "tree exclude: no files matched");
Ok(true)
}
fn create_match_list<'a>(
list: &'a Option<Vec<String>>,
default: &'a str,
) -> Result<Any<'a>> {
let any = match list {
None => wax::any([default])?,
Some(list) => {
let list: Vec<&str> = list.iter().map(|s| &s[..]).collect();
wax::any(list)?
}
};
Ok(any)
}