110 lines
3.3 KiB
Rust
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)
|
|
}
|