backend.rs: expanded git convenience types and moved to git.rs
This commit is contained in:
@@ -46,15 +46,14 @@
|
||||
|
||||
use std::{
|
||||
error::Error,
|
||||
path::{ PathBuf, Path },
|
||||
path::PathBuf,
|
||||
};
|
||||
|
||||
use git2::{ Commit, Repository, Sort };
|
||||
use serde::Serialize;
|
||||
use git2::{ Branch, Commit, Repository, Sort, TreeEntry };
|
||||
|
||||
#[derive(Serialize)]
|
||||
pub struct GitCommit {
|
||||
author: (Option<String>, Option<String>), // name, e-mail
|
||||
entries: Vec<GitEntry>,
|
||||
hash: String,
|
||||
message: Option<String>,
|
||||
short_hash: Option<String>,
|
||||
@@ -62,7 +61,7 @@ pub struct GitCommit {
|
||||
}
|
||||
|
||||
impl TryFrom<Commit<'_>> for GitCommit {
|
||||
type Error = git2::Error;
|
||||
type Error = Box<dyn Error>;
|
||||
|
||||
fn try_from(commit: Commit) -> Result<Self, Self::Error> {
|
||||
let hash = commit.id().to_string();
|
||||
@@ -73,29 +72,77 @@ impl TryFrom<Commit<'_>> for GitCommit {
|
||||
let address = commit_signature.email().map(|f| f.to_owned());
|
||||
let author = (name, address);
|
||||
let time = commit.time().seconds();
|
||||
let entries = commit
|
||||
.tree()?
|
||||
.iter()
|
||||
.map(|c| -> Result<GitEntry, std::string::FromUtf8Error> {
|
||||
Ok(GitEntry::try_from(c)?)
|
||||
}).collect::<Result<Vec<_>, _>>()?;
|
||||
|
||||
Ok(GitCommit { author, hash, message, short_hash, time })
|
||||
Ok(GitCommit { author, entries, hash, message, short_hash, time })
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
pub struct GitEntry {
|
||||
last_commit: GitCommit,
|
||||
path: String,
|
||||
}
|
||||
|
||||
impl GitEntry {
|
||||
fn new(commit: GitCommit, path: String) -> Self {
|
||||
GitEntry { last_commit: commit, path }
|
||||
fn new(path: String) -> Self {
|
||||
GitEntry { path }
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<TreeEntry<'_>> for GitEntry {
|
||||
type Error = std::string::FromUtf8Error;
|
||||
|
||||
fn try_from(entry: TreeEntry) -> Result<Self, Self::Error> {
|
||||
let path = String::from_utf8(entry.name_bytes().to_vec())?;
|
||||
Ok(Self { path })
|
||||
}
|
||||
}
|
||||
|
||||
pub struct GitBranch {
|
||||
commits: Vec<GitCommit>,
|
||||
name: String,
|
||||
}
|
||||
|
||||
struct GitBranchWrapper<'a> {
|
||||
branch: Branch<'a>,
|
||||
repo: &'a Repository,
|
||||
}
|
||||
|
||||
impl<'a> GitBranchWrapper<'a> {
|
||||
fn new(branch: Branch<'a>, repo: &'a Repository) -> Self {
|
||||
Self { branch, repo }
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<GitBranchWrapper<'_>> for GitBranch {
|
||||
type Error = Box<dyn Error>;
|
||||
|
||||
fn try_from(branch: GitBranchWrapper) -> Result<Self, Self::Error> {
|
||||
let name = String::from_utf8(branch.branch.name_bytes()?.to_vec())?;
|
||||
let repo = branch.repo;
|
||||
let branch_oid = branch.branch.get().target().unwrap();
|
||||
|
||||
let mut revwalk = repo.revwalk()?;
|
||||
revwalk.set_sorting(Sort::TOPOLOGICAL | Sort::TIME)?;
|
||||
revwalk.push(branch_oid)?;
|
||||
|
||||
let commits = revwalk
|
||||
.into_iter()
|
||||
.map(|o| -> Result<GitCommit, Box<dyn Error>> {
|
||||
Ok(GitCommit::try_from(repo.find_commit(o?)?)?)
|
||||
}).collect::<Result<Vec<_>, _>>()?;
|
||||
|
||||
Ok(GitBranch { commits, name })
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
pub struct GitRepo {
|
||||
branch: Option<String>,
|
||||
entries: Vec<GitEntry>,
|
||||
last_commit: GitCommit,
|
||||
branches: Vec<GitBranch>,
|
||||
name: String,
|
||||
owner: String,
|
||||
}
|
||||
@@ -103,7 +150,23 @@ pub struct GitRepo {
|
||||
impl GitRepo {
|
||||
fn open(path: PathBuf) -> Result<Self, Box<dyn Error>> {
|
||||
let repo = Repository::open(path.clone())?;
|
||||
let entries = Self::get_entries(&repo)?;
|
||||
|
||||
let branches = repo
|
||||
.branches(None)?
|
||||
.map(|b| -> Result<GitBranch, Box<dyn Error>> {
|
||||
Ok(GitBranch::try_from(GitBranchWrapper::new(b?.0, &repo))?)
|
||||
}).collect::<Result<Vec<_>, _>>()?;
|
||||
/*
|
||||
let mut revwalk = repo.revwalk()?;
|
||||
|
||||
revwalk.set_sorting(Sort::TOPOLOGICAL | Sort::TIME)?;
|
||||
revwalk.push_head()?;
|
||||
let commits = revwalk
|
||||
.into_iter()
|
||||
.map(|o| -> Result<GitCommit, Box<dyn Error>> {
|
||||
Ok(GitCommit::try_from(repo.find_commit(o?)?)?)
|
||||
}).collect::<Result<Vec<_>, _>>()?;
|
||||
*/
|
||||
|
||||
let full_path = path.clone().as_path().canonicalize()?;
|
||||
|
||||
@@ -128,53 +191,10 @@ impl GitRepo {
|
||||
.to_vec()
|
||||
)?;
|
||||
|
||||
let head = repo.head()?;
|
||||
let branch = head.shorthand().map(|f| f.to_owned());
|
||||
|
||||
let last_commit = GitCommit::try_from(head.peel_to_commit()?)?;
|
||||
|
||||
Ok(GitRepo { branch, entries, last_commit, name, owner })
|
||||
Ok(GitRepo { branches, name, owner })
|
||||
}
|
||||
|
||||
fn get_remote_repo() { // for AP repos
|
||||
todo!();
|
||||
}
|
||||
|
||||
fn get_entries(repo: &Repository) -> Result<Vec<GitEntry>, Box<dyn Error>> {
|
||||
let mut entries = Vec::new();
|
||||
let mut revwalk = repo.revwalk()?;
|
||||
|
||||
revwalk.set_sorting(Sort::TOPOLOGICAL | Sort::TIME)?;
|
||||
revwalk.push_head()?;
|
||||
|
||||
for commit_id in revwalk {
|
||||
let commit_id = commit_id?;
|
||||
let commit = repo.find_commit(commit_id)?;
|
||||
if commit.parent_count() <= 1 {
|
||||
let tree = commit.tree()?;
|
||||
let prev_tree = match commit.parent_count() {
|
||||
1 => Some(commit.parent(0)?.tree()?),
|
||||
0 => None,
|
||||
_ => unreachable!(),
|
||||
};
|
||||
|
||||
let diff = repo
|
||||
.diff_tree_to_tree(prev_tree.as_ref(), Some(&tree), None)?;
|
||||
|
||||
for delta in diff.deltas() {
|
||||
if let Some(file_path) = delta.new_file().path() {
|
||||
let p = String::from_utf8(file_path
|
||||
.to_path_buf()
|
||||
.as_mut_os_string()
|
||||
.as_encoded_bytes()
|
||||
.to_vec()
|
||||
)?;
|
||||
let c = GitCommit::try_from(commit.clone())?;
|
||||
entries.push(GitEntry::new(c, p));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(entries)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user