summaryrefslogtreecommitdiff
path: root/server/src/git.rs
diff options
context:
space:
mode:
Diffstat (limited to 'server/src/git.rs')
-rw-r--r--server/src/git.rs64
1 files changed, 64 insertions, 0 deletions
diff --git a/server/src/git.rs b/server/src/git.rs
index 9fb0593..7add644 100644
--- a/server/src/git.rs
+++ b/server/src/git.rs
@@ -31,6 +31,8 @@ impl fmt::Display for Error {
impl std::error::Error for Error {}
+pub const EMPTY: &str = "0000000000000000000000000000000000000000";
+
struct RepoData {
// Only one fetch at a time, and they should be in queue
fetch_semaphore: Semaphore,
@@ -50,10 +52,30 @@ pub struct Repository {
lock: RwLock<RepoData>,
}
+#[allow(dead_code)]
+pub struct User {
+ pub name: String,
+ pub email: String,
+ // Part before '@' in email
+ pub username: String,
+}
+
fn io_err(action: &str, e: std::io::Error) -> Error {
Error::new(format!("{action}: {e}"))
}
+fn parse_user(output: String) -> User {
+ let mut lines = output.lines();
+ let name = lines.next().unwrap_or("").to_string();
+ let username = lines.next().unwrap_or("").to_string();
+ let email = lines.next().unwrap_or("").to_string();
+ User {
+ name,
+ email,
+ username,
+ }
+}
+
impl RepoData {
fn new() -> Self {
Self {
@@ -246,6 +268,34 @@ impl RepoData {
self.check(&mut cmd).await
}
+ async fn get_author(&self, repo: &Repository, commit: &str) -> Result<User, Error> {
+ self.get_log_format(repo, commit, "%an%n%al%n%ae")
+ .map_ok(|output| parse_user(output))
+ .await
+ }
+
+ async fn get_commiter(&self, repo: &Repository, commit: &str) -> Result<User, Error> {
+ self.get_log_format(repo, commit, "%cn%n%cl%n%ce")
+ .map_ok(|output| parse_user(output))
+ .await
+ }
+
+ async fn get_log_format(
+ &self,
+ repo: &Repository,
+ commit: &str,
+ format: &str,
+ ) -> Result<String, Error> {
+ let mut cmd = self.git_cmd(repo);
+ cmd.arg("log")
+ .arg("-1")
+ .arg("--no-decorate")
+ .arg("--no-mailmap")
+ .arg(format!("--pretty=format:{format}"))
+ .arg(commit);
+ self.output(&mut cmd).await
+ }
+
fn git_cmd(&self, repo: &Repository) -> Command {
let mut cmd = Command::new("git");
// Run as if git was started in <path> instead of the current working directory.
@@ -445,6 +495,20 @@ impl Repository {
data.is_equal_content(self, commit1.as_str(), commit2.as_str())
.await
}
+
+ pub async fn get_author(&self, commit: impl Into<String>) -> Result<User, Error> {
+ let commit = commit.into();
+ let data = self.lock.read().await;
+
+ data.get_author(self, commit.as_str()).await
+ }
+
+ pub async fn get_commiter(&self, commit: impl Into<String>) -> Result<User, Error> {
+ let commit = commit.into();
+ let data = self.lock.read().await;
+
+ data.get_commiter(self, commit.as_str()).await
+ }
}
#[cfg(not(test))]