diff options
Diffstat (limited to 'server/src/git.rs')
| -rw-r--r-- | server/src/git.rs | 64 |
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))] |
