use std::ops::Add; use git2::{ObjectType, Oid, Repository, BranchType}; use crate::git::GitBrowseEntry; use crate::gitcommit::GitRef; use crate::gitdir::GitDir; use crate::gitfile::GitFile; use std::path::{PathBuf, Path}; use std::str::FromStr; pub struct GitRepo { git2 : Repository, } impl GitRepo { pub fn new(path : &str) -> Result { Repository::open(path).map(|git2| GitRepo{git2}) } pub fn get_root_tree<'a, 'b> (&'a self, commit : &'b GitRef, path : &Path) -> Result, git2::Error> { let commit = match commit { GitRef::Commit(commit) => { let oid = Oid::from_str(commit.as_str())?; self.git2.find_commit(oid)? } GitRef::Branch(branch) => { let branch = self.git2.find_branch(branch.as_str(), BranchType::Local)?; branch.get().peel_to_commit()? } GitRef::Head => { let head = self.git2.head()?; head.peel_to_commit()? } }; let tree = commit.tree()?; tree.get_path(path)?. let fullname = PathBuf::from("/"); Ok(GitDir { fullname, tree }) } pub async fn browse<'a>(&'a self, dir: &GitDir<'a>) -> Result>, git2::Error> { let mut res = Vec::new(); for entry in dir.tree.iter() { match entry.kind() { None => {Err(git2::Error::from_str("each tree entry must be well defined"))?;} Some(kind) => match kind { ObjectType::Any => {Err(git2::Error::from_str("tree entry cannot be of kind Any"))?;} ObjectType::Commit => {Err(git2::Error::from_str("tree entry cannot be of kind Commit"))?;} ObjectType::Tree => { let name = entry.name().ok_or(git2::Error::from_str("entry must have valid utf8 name"))?; let mut fullname = dir.fullname.clone(); fullname.push(name); let subtree = self.git2.find_tree(entry.id())?; res.push(GitBrowseEntry::EGitDir(GitDir {fullname, tree : subtree})); } ObjectType::Blob => { let name = entry.name().ok_or(git2::Error::from_str("entry must have valid utf8 name"))?; let mut fullname = dir.fullname.clone(); fullname.push(name); res.push(GitBrowseEntry::EGitFile(GitFile::new(fullname))); } ObjectType::Tag => {Err(git2::Error::from_str("tree entry cannot be of kind tag"))?;} } }; } return Ok(res); } }