parent
eaf889ee80
commit
eb1b781fab
@ -0,0 +1,51 @@ |
||||
use super::{HashId, RawRepository}; |
||||
use crate::Branch; |
||||
use git2::{Commit, Repository}; |
||||
|
||||
/// Represent some raw branch metadata
|
||||
pub struct RawBranch { |
||||
pub name: String, |
||||
pub head: HashId, |
||||
} |
||||
|
||||
fn print_commit(i: &String, c: &Commit) { |
||||
println!( |
||||
"{}{}: {}", |
||||
i, |
||||
c.id().to_string(), |
||||
c.message().unwrap().trim().split("\n").nth(0).unwrap() |
||||
); |
||||
} |
||||
|
||||
fn print_parent_tree(c: &Commit, indent: String) { |
||||
c.parents().for_each(|c| { |
||||
println!( |
||||
"{}{}: {}", |
||||
indent, |
||||
c.id().to_string(), |
||||
c.message().unwrap().trim().split("\n").nth(0).unwrap() |
||||
); |
||||
|
||||
print_parent_tree(&c, indent.clone()); |
||||
}); |
||||
} |
||||
|
||||
impl RawBranch { |
||||
/// Consume branch reference and enumerate real branch history
|
||||
pub fn into_branch(self, repo: &mut RawRepository) -> Branch { |
||||
todo!() |
||||
} |
||||
|
||||
/// **REMOVE ME** A test function to do some test things
|
||||
pub fn enumerate(&self, indent: String, repo: &Repository) { |
||||
let c = repo.find_commit((&self.head).into()).unwrap(); |
||||
println!( |
||||
"{}{}: {}", |
||||
indent, |
||||
c.id().to_string(), |
||||
c.message().unwrap().trim().split("\n").nth(0).unwrap() |
||||
); |
||||
|
||||
print_parent_tree(&c, indent); |
||||
} |
||||
} |
@ -1 +1,168 @@ |
||||
//! Walk the file tree for a particular commit
|
||||
|
||||
use git2::{self, ObjectType, TreeWalkMode}; |
||||
use std::collections::BTreeMap; |
||||
|
||||
/// A cache of a repository tree
|
||||
#[derive(Default, Debug, Clone)] |
||||
pub(crate) struct Tree { |
||||
inner: BTreeMap<String, TreeNode>, |
||||
} |
||||
|
||||
impl Tree { |
||||
/// Insert a node into a subtree with it's full path
|
||||
fn insert_to_subtree(&mut self, mut path: Vec<String>, name: String, node: TreeNode) { |
||||
// If we are given a path, resolve it first
|
||||
let curr = if path.len() > 0 { |
||||
let rest = path.split_off(1); |
||||
let mut curr = self.inner.get_mut(&path[0]).unwrap(); |
||||
|
||||
for dir in rest { |
||||
match curr { |
||||
TreeNode::Dir(ref mut d) => { |
||||
curr = d.children.inner.get_mut(&dir).unwrap(); |
||||
} |
||||
_ => panic!("Not a tree!"), |
||||
} |
||||
} |
||||
|
||||
match curr { |
||||
TreeNode::Dir(ref mut d) => &mut d.children, |
||||
TreeNode::File(_) => panic!("Not a tree!"), |
||||
} |
||||
} else { |
||||
// If no path was given, we assume the root is meant
|
||||
self |
||||
}; |
||||
|
||||
curr.inner.insert(name, node); |
||||
} |
||||
|
||||
/// Walk through the tree and only return filenode objects
|
||||
pub(crate) fn flatten(&self) -> Vec<FileNode> { |
||||
self.inner.values().fold(vec![], |mut vec, node| { |
||||
match node { |
||||
TreeNode::File(f) => vec.push(f.clone()), |
||||
TreeNode::Dir(d) => vec.append(&mut d.children.flatten()), |
||||
} |
||||
|
||||
vec |
||||
}) |
||||
} |
||||
|
||||
/// Get all the commits that touch a file
|
||||
pub(crate) fn grab_path_history(&self, path: String) -> String { |
||||
let mut path: Vec<String> = path |
||||
.split("/") |
||||
.filter_map(|seg| match seg { |
||||
"" => None, |
||||
val => Some(val.into()), |
||||
}) |
||||
.collect(); |
||||
|
||||
let leaf = if path.len() > 0 { |
||||
let rest = path.split_off(1); |
||||
let mut curr = self.inner.get(&path[0]).unwrap(); |
||||
|
||||
for dir in rest { |
||||
match curr { |
||||
TreeNode::Dir(d) => curr = d.children.inner.get(&dir).unwrap(), |
||||
TreeNode::File(_) => break, // we reached the leaf
|
||||
} |
||||
} |
||||
|
||||
curr |
||||
} else { |
||||
panic!("No valid path!"); |
||||
}; |
||||
|
||||
match leaf { |
||||
TreeNode::File(f) => f.id.clone(), |
||||
_ => panic!("Not a leaf!"), |
||||
} |
||||
} |
||||
} |
||||
|
||||
#[derive(Clone, Debug)] |
||||
pub(crate) enum TreeNode { |
||||
File(FileNode), |
||||
Dir(DirNode), |
||||
} |
||||
|
||||
impl TreeNode { |
||||
fn name(&self) -> String { |
||||
match self { |
||||
Self::File(f) => f.name.clone(), |
||||
Self::Dir(d) => d.name.clone(), |
||||
} |
||||
} |
||||
} |
||||
|
||||
#[derive(Clone, Debug)] |
||||
pub(crate) struct FileNode { |
||||
pub id: String, |
||||
pub path: Vec<String>, |
||||
pub name: String, |
||||
} |
||||
|
||||
#[derive(Clone, Debug)] |
||||
pub(crate) struct DirNode { |
||||
pub path: Vec<String>, |
||||
pub name: String, |
||||
pub children: Tree, |
||||
} |
||||
|
||||
impl DirNode { |
||||
fn append(&mut self, node: TreeNode) { |
||||
self.children.inner.insert(node.name(), node); |
||||
} |
||||
} |
||||
|
||||
/// Take a series of path-segments and render a tree at that location
|
||||
pub(crate) fn parse_tree(tree: git2::Tree) -> Tree { |
||||
let mut root = Tree::default(); |
||||
|
||||
tree.walk(TreeWalkMode::PreOrder, |path, entry| { |
||||
let path: Vec<String> = path |
||||
.split("/") |
||||
.filter_map(|seg| match seg { |
||||
"" => None, |
||||
val => Some(val.into()), |
||||
}) |
||||
.collect(); |
||||
let name = entry.name().unwrap().to_string(); |
||||
|
||||
match entry.kind() { |
||||
// For every tree in the tree we create a new TreeNode with the path we know about
|
||||
Some(ObjectType::Tree) => { |
||||
root.insert_to_subtree( |
||||
path.clone(), |
||||
name.clone(), |
||||
TreeNode::Dir(DirNode { |
||||
path, |
||||
name, |
||||
children: Tree::default(), |
||||
}), |
||||
); |
||||
} |
||||
// If we encounter a blob, this is a file that we can simply insert into the tree
|
||||
Some(ObjectType::Blob) => { |
||||
root.insert_to_subtree( |
||||
path.clone(), |
||||
name.clone(), |
||||
TreeNode::File(FileNode { |
||||
id: format!("{}", entry.id()), |
||||
path, |
||||
name, |
||||
}), |
||||
); |
||||
} |
||||
_ => {} |
||||
} |
||||
|
||||
0 |
||||
}) |
||||
.unwrap(); |
||||
|
||||
root |
||||
} |
||||
|
Loading…
Reference in new issue