My personal project and infrastructure archive
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 
nomicon/apps/servers/octopus/supergit/src/files/tree_utils.rs

96 lines
2.5 KiB

//! A set of tree utilities used internally in the tree.rs module
use crate::HashId;
use git2::{Repository, Tree};
use std::{iter::Peekable, path::PathBuf, sync::Arc};
pub(super) trait PairIter<I, K>
where
I: Iterator<Item = K>,
{
/// Step through
fn pairs<'i, F: FnMut(K, Option<&K>)>(&'i mut self, cb: F);
fn next_pair<'i>(&'i mut self) -> (Option<K>, Option<&K>);
}
impl<I, K> PairIter<I, K> for Peekable<I>
where
I: Iterator<Item = K>,
{
fn pairs<'i, F: FnMut(K, Option<&K>)>(&'i mut self, mut cb: F) {
// Iterate until a->None
while let (Some(a), b) = self.next_pair() {
cb(a, b);
}
}
fn next_pair<'i>(&'i mut self) -> (Option<K>, Option<&K>) {
(self.next(), self.peek())
}
}
/// Take a vector of path segments, and turn it into a valid offset path
///
/// There are tests to make sure this function works properly.
/// Following are some example transformations.
///
/// * vec![] -> ""
/// * vec!["foo"] -> "foo"
/// * vec!["foo", "bar", "baz"] -> "foo/bar/baz"
pub(super) fn path_segs_join(segments: Vec<&str>) -> String {
segments
.into_iter()
.fold(PathBuf::new(), |buf, seg| buf.join(seg))
.as_path()
.to_str()
.unwrap()
.to_owned()
}
/// Take an offset path inside the repository and split it into a vec
pub(super) fn path_split(path: &str) -> Vec<&str> {
path.split("/").filter(|s| s != &"").collect()
}
/// Compare a path and entry to a target buffer
pub(super) fn path_cmp(target: &Vec<&str>, path: &str, entry: &str) -> bool {
let mut buf = path_split(path);
buf.push(entry);
target == &buf
}
/// Open a tree for a particular commit
pub(super) fn open_tree<'r>(repo: &'r Arc<Repository>, c: &HashId) -> Option<Tree<'r>> {
repo.find_commit(c.to_oid()).unwrap().tree().ok()
}
#[test]
fn empty_path() {
assert_eq!(path_segs_join(vec![]), String::from(""));
}
#[test]
fn one_path() {
assert_eq!(path_segs_join(vec!["foo".into()]), String::from("foo"));
}
#[test]
fn nested_path() {
assert_eq!(
path_segs_join(vec!["foo".into(), "bar".into(), "baz".into()]),
String::from("foo/bar/baz")
);
}
#[test]
fn pair_iterator() {
// The pair iterator needs access to `peek()`
let mut i = vec![1, 2, 3, 4].into_iter().peekable();
assert_eq!(i.next_pair(), (Some(1), Some(&2)));
assert_eq!(i.next_pair(), (Some(2), Some(&3)));
assert_eq!(i.next_pair(), (Some(3), Some(&4)));
assert_eq!(i.next_pair(), (Some(4), None));
}