diff --git a/Cargo.toml b/Cargo.toml index a1f06c4..6198d79 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -5,7 +5,9 @@ authors = ["Vladan Popovic "] edition = "2018" [dependencies] +axum = "0.6.18" chrono = { version = "*" } +tokio = { version = "1.28.1", features = ["tokio-macros"] } [dependencies.git2] version = "*" diff --git a/src/git/blame.rs b/src/git/blame.rs index caacab0..ac68dca 100644 --- a/src/git/blame.rs +++ b/src/git/blame.rs @@ -1,4 +1,4 @@ -use crate::errors::SocialError; +use crate::git::error::SocialError; use crate::git::repo::SocialRepo; use crate::git::{SocialBlame, SocialBlameHunk}; use git2::{Blame, BlameHunk, BlameOptions}; diff --git a/src/git/diff.rs b/src/git/diff.rs index ef7e7c2..cb54445 100644 --- a/src/git/diff.rs +++ b/src/git/diff.rs @@ -1,4 +1,4 @@ -use crate::errors::SocialError; +use crate::git::error::SocialError; use crate::git::repo::SocialRepo; use crate::git::SocialDiff; use git2::{Diff, DiffOptions}; diff --git a/src/errors.rs b/src/git/error.rs similarity index 100% rename from src/errors.rs rename to src/git/error.rs diff --git a/src/git/log.rs b/src/git/log.rs index 9e03c16..6aaf3ed 100644 --- a/src/git/log.rs +++ b/src/git/log.rs @@ -1,4 +1,4 @@ -use crate::errors::SocialError; +use crate::git::error::SocialError; use crate::git::repo::SocialRepo; use crate::git::SocialCommit; @@ -63,13 +63,13 @@ impl Log for SocialRepo { .take(1) .next() .map(|r| { - r.map_err(|_| SocialError { - message: "Invalid commit reference!".to_string(), + r.map_err(|err| SocialError { + message: format!("Invalid commit! {}", err) }) .map(|c| c.into()) }) .ok_or(SocialError { - message: "Repo doesn't contain any commits!".to_owned(), + message: format!("Repo doesn't contain any commits!") })? } } diff --git a/src/git/mod.rs b/src/git/mod.rs index 14b8698..e921a90 100644 --- a/src/git/mod.rs +++ b/src/git/mod.rs @@ -1,5 +1,6 @@ pub(crate) mod blame; pub(crate) mod diff; +pub(crate) mod error; pub(crate) mod log; pub(crate) mod references; pub(crate) mod repo; diff --git a/src/git/reference.rs b/src/git/reference.rs new file mode 100644 index 0000000..811ffc2 --- /dev/null +++ b/src/git/reference.rs @@ -0,0 +1,67 @@ +use crate::git::log::into_social_commit; +use crate::git::repository::SocialRepo; +use crate::git::Error; +use git2::{Branch, BranchType, Commit}; +use shared::{SocialBranch, SocialCommit, SocialTag}; + +fn into_social_branch(b: Branch<'_>) -> SocialBranch { + SocialBranch { + name: b.name().unwrap_or(Some("")).unwrap_or("").to_owned(), + head: SocialCommit::default(), + } +} + +fn into_social_tag(name: Option<&str>) -> SocialTag { + SocialTag { + name: name.unwrap_or("").to_owned(), + head: SocialCommit::default(), + annotation: None, + } +} + +pub trait Refs { + fn branches(&self) -> Result, Error>; + fn tags(&self) -> Result, Error>; +} + +impl Refs for SocialRepo { + fn branches(&self) -> Result, Error> { + let all_branches = self.repo.branches(Some(BranchType::Local))?; + let mut resulting_brances: Vec = vec![]; + + for r in all_branches { + r.map(|(branch, _)| { + let mut sb = into_social_branch(branch); + self.repo + .revparse_single(&sb.name) + .map(|obj| { + obj.peel_to_commit() + .map(|c: Commit| { + sb.head = into_social_commit(c); + resulting_brances.push(sb); + }) + .unwrap_or(()); + }) + .unwrap_or(()); + }) + .unwrap_or(()); + } + Ok(resulting_brances) + } + + fn tags(&self) -> Result, Error> { + let tagnames = self.repo.tag_names(None)?; + let mut result: Vec = vec![]; + + for t in tagnames.into_iter() { + let mut st = into_social_tag(t); + let _ = self.repo.revparse_single(&st.name).map(|obj| { + obj.peel_to_commit().map(|c: Commit| { + st.head = into_social_commit(c); + result.push(st); + }) + }); + } + Ok(result) + } +} diff --git a/src/git/references.rs b/src/git/references.rs index e821f07..4e0ab87 100644 --- a/src/git/references.rs +++ b/src/git/references.rs @@ -1,4 +1,4 @@ -use crate::errors::SocialError; +use crate::git::error::SocialError; use crate::git::repo::SocialRepo; use crate::git::{SocialBranch, SocialCommit, SocialTag}; use git2::{Branch, BranchType, Commit}; diff --git a/src/git/repo.rs b/src/git/repo.rs index e4be036..38a9187 100644 --- a/src/git/repo.rs +++ b/src/git/repo.rs @@ -1,4 +1,4 @@ -use crate::errors::SocialError; +use crate::git::error::SocialError; use git2::{Error as GitError, Repository, Tree}; use std::{fs::read_to_string, path::Path}; @@ -22,6 +22,7 @@ impl<'repo> SocialRepo { .and_then(|obj| obj.peel_to_tree()) } + #[allow(dead_code)] pub fn get_description(&self) -> String { // The description is in a file named "description", // in the .git directory, or the root directory if bare. diff --git a/src/git/repository.rs b/src/git/repository.rs new file mode 100644 index 0000000..07ebe53 --- /dev/null +++ b/src/git/repository.rs @@ -0,0 +1,34 @@ +use crate::errors::SocialError; +use git2::{Error as GitError, Repository, Tree}; +use std::{fs::read_to_string, path::Path}; + +pub struct SocialRepo { + pub repo: Repository, +} + +unsafe impl Send for SocialRepo {} +unsafe impl Sync for SocialRepo {} + +impl SocialRepo { + pub fn new(path: &str) -> Result { + Repository::open(path) + .map(|repo| Self { repo }) + .map_err(|_| { + let err = "fatal: not a git repository"; + SocialError::from(err) + }) + } + + pub fn get_tree(&self, rev: &str) -> Result { + self.repo + .revparse_single(rev) + .and_then(|obj| obj.peel_to_tree()) + } + + pub fn get_description(&self) -> String { + // The description is in a file named "description", + // in the .git directory, or the root directory if bare. + let git_path = self.repo.path().join(Path::new("description")); + read_to_string(git_path).unwrap_or("".to_string()) + } +} diff --git a/src/git/tree.rs b/src/git/tree.rs index 0056c27..2936f4b 100644 --- a/src/git/tree.rs +++ b/src/git/tree.rs @@ -1,4 +1,4 @@ -use crate::errors::SocialError; +use crate::git::error::SocialError; use crate::git::repo::SocialRepo; use crate::git::{SocialFileContent, SocialTreeEntry}; use git2::{Blob, Error as GitError, Object, ObjectType, TreeEntry}; @@ -65,9 +65,7 @@ impl LsTree for SocialRepo { }) .and_then(|blob: &Blob| { String::from_utf8(blob.content().to_vec()).map_err(|_| { - GitError::from_str( - format!("Cannot read file {}", path.display()).as_ref(), - ) + GitError::from_str(format!("Cannot read file {}", path.display()).as_ref()) }) }) .map(|content| SocialFileContent { diff --git a/src/main.rs b/src/main.rs index 86d3328..b5e8cab 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,4 +1,3 @@ -mod errors; mod git; use git::repo::SocialRepo;