Extract git commands to own module

This commit is contained in:
Joscha 2023-08-17 15:01:00 +02:00
parent f12da915a9
commit 546de29706
5 changed files with 85 additions and 39 deletions

79
src/git.rs Normal file
View file

@ -0,0 +1,79 @@
//! Execute git binary commands.
use std::{
error, fmt, io,
path::Path,
process::{Command, Output},
};
use log::trace;
#[derive(Debug)]
pub enum Error {
Io(io::Error),
Command(Command, Output),
}
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Error::Io(e) => e.fmt(f),
Error::Command(command, output) => {
write!(f, "Command exited with {}", output.status)?;
write!(f, "COMMAND: {command:?}")?;
if !output.stdout.is_empty() {
let stdout = String::from_utf8_lossy(&output.stdout);
write!(f, "STDOUT:\n{}", stdout.trim_end())?;
}
if !output.stderr.is_empty() {
let stderr = String::from_utf8_lossy(&output.stderr);
write!(f, "STDERR:\n{}", stderr.trim_end())?;
}
Ok(())
}
}
}
}
impl error::Error for Error {}
impl From<io::Error> for Error {
fn from(value: io::Error) -> Self {
Self::Io(value)
}
}
fn run(mut command: Command) -> Result<Output, Error> {
let output = command.output()?;
if output.status.success() {
trace!("Command exited with {}", output.status);
trace!("COMMAND: {command:?}");
if !output.stdout.is_empty() {
let stdout = String::from_utf8_lossy(&output.stdout);
trace!("STDOUT:\n{}", stdout.trim_end());
}
if !output.stderr.is_empty() {
let stderr = String::from_utf8_lossy(&output.stderr);
trace!("STDERR:\n{}", stderr.trim_end());
}
Ok(output)
} else {
Err(Error::Command(command, output))
}
}
pub fn fetch(path: &Path, url: &str, refspecs: &[String]) -> Result<(), Error> {
let mut command = Command::new("git");
command
.arg("fetch")
.arg("-C")
.arg(path)
.arg("--prune")
.arg("--")
.arg(url);
for refspec in refspecs {
command.arg(refspec);
}
run(command)?;
Ok(())
}

View file

@ -4,6 +4,7 @@
mod args; mod args;
mod config; mod config;
mod git;
mod id; mod id;
mod server; mod server;
mod shared; mod shared;

View file

@ -1,51 +1,17 @@
//! Update repo refs using the `git` binary. //! Update repo refs using the `git` binary.
use std::process::Command;
use gix::bstr::ByteSlice;
use log::{info, warn}; use log::{info, warn};
use crate::{config::ServerConfig, server::Repo, somehow}; use crate::{config::ServerConfig, git, server::Repo, somehow};
fn fetch(repo: Repo, url: &str, refspecs: &[String]) -> somehow::Result<()> {
info!("Fetching refs from {url}");
let mut command = Command::new("git");
command
.arg("fetch")
.arg("-C")
.arg(repo.0.path())
.arg("--prune")
.arg("--")
.arg(url);
for refspec in refspecs {
command.arg(refspec);
}
let output = command.output()?;
if output.status.success() {
} else {
warn!(
"Error fetching refs:\n\
{command:?} exited with code {}\n\
STDOUT:\n{}\n\
STDERR:\n{}",
output.status,
output.stdout.to_str_lossy(),
output.stderr.to_str_lossy()
);
}
Ok(())
}
async fn inner(repo: Repo, url: &'static str, refspecs: &'static [String]) -> somehow::Result<()> { async fn inner(repo: Repo, url: &'static str, refspecs: &'static [String]) -> somehow::Result<()> {
tokio::task::spawn_blocking(move || fetch(repo, url, refspecs)).await??; tokio::task::spawn_blocking(move || git::fetch(repo.0.path(), url, refspecs)).await??;
Ok(()) Ok(())
} }
pub(super) async fn update(config: &'static ServerConfig, repo: Repo) { pub(super) async fn update(config: &'static ServerConfig, repo: Repo) {
if let Some(url) = &config.repo_fetch_url { if let Some(url) = &config.repo_fetch_url {
info!("Fetching refs from {url}");
if let Err(e) = inner(repo, url, &config.repo_fetch_refspecs).await { if let Err(e) = inner(repo, url, &config.repo_fetch_refspecs).await {
warn!("Error fetching refs:\n{e:?}"); warn!("Error fetching refs:\n{e:?}");
} }

View file

@ -5,7 +5,6 @@ use time::OffsetDateTime;
use crate::somehow; use crate::somehow;
async fn inner(db: &SqlitePool) -> somehow::Result<()> { async fn inner(db: &SqlitePool) -> somehow::Result<()> {
debug!("Updating queue");
let mut tx = db.begin().await?; let mut tx = db.begin().await?;
let conn = tx.acquire().await?; let conn = tx.acquire().await?;
@ -40,6 +39,7 @@ async fn inner(db: &SqlitePool) -> somehow::Result<()> {
} }
pub(super) async fn update(db: &SqlitePool) { pub(super) async fn update(db: &SqlitePool) {
debug!("Updating queue");
if let Err(e) = inner(db).await { if let Err(e) = inner(db).await {
warn!("Error updating queue:\n{e:?}"); warn!("Error updating queue:\n{e:?}");
} }

View file

@ -235,7 +235,6 @@ async fn update_commit_tracked_status(conn: &mut SqliteConnection) -> somehow::R
} }
pub async fn inner(db: &SqlitePool, repo: Repo) -> somehow::Result<()> { pub async fn inner(db: &SqlitePool, repo: Repo) -> somehow::Result<()> {
debug!("Updating repo data");
let thread_local_repo = repo.0.to_thread_local(); let thread_local_repo = repo.0.to_thread_local();
let mut tx = db.begin().await?; let mut tx = db.begin().await?;
let conn = tx.acquire().await?; let conn = tx.acquire().await?;
@ -290,6 +289,7 @@ pub async fn inner(db: &SqlitePool, repo: Repo) -> somehow::Result<()> {
} }
pub(super) async fn update(db: &SqlitePool, repo: Repo) { pub(super) async fn update(db: &SqlitePool, repo: Repo) {
debug!("Updating repo data");
if let Err(e) = inner(db, repo).await { if let Err(e) = inner(db, repo).await {
warn!("Error updating repo data:\n{e:?}"); warn!("Error updating repo data:\n{e:?}");
} }