Initialize repo if fetch url is configured

This commit is contained in:
Joscha 2023-08-17 15:08:09 +02:00
parent 546de29706
commit 5ca8fee66a
2 changed files with 89 additions and 6 deletions

View file

@ -6,7 +6,8 @@ use std::{
process::{Command, Output}, process::{Command, Output},
}; };
use log::trace; use log::{trace, warn};
use regex::bytes::Regex;
#[derive(Debug)] #[derive(Debug)]
pub enum Error { pub enum Error {
@ -62,6 +63,45 @@ fn run(mut command: Command) -> Result<Output, Error> {
} }
} }
pub fn init_bare(path: &Path) -> Result<(), Error> {
let mut command = Command::new("git");
command.arg("init").arg("--bare").arg("--").arg(path);
run(command)?;
Ok(())
}
pub fn fetch_head(path: &Path, url: &str) -> Result<(), Error> {
let mut command = Command::new("git");
command
.arg("-C")
.arg(path)
.arg("ls-remote")
.arg("--symref")
.arg("--")
.arg(url)
.arg("HEAD"); // Includes other refs like refs/foo/HEAD
let output = run(command)?;
let regex = Regex::new(r"(?m)^ref: (refs/\S+)\s+HEAD$").unwrap();
let Some(captures) = regex.captures(&output.stdout) else {
warn!("Did not find HEAD of {url}");
return Ok(());
};
let head = String::from_utf8_lossy(captures.get(1).unwrap().as_bytes());
let mut command = Command::new("git");
command
.arg("-C")
.arg(path)
.arg("symbolic-ref")
.arg("--")
.arg("HEAD")
.arg(&head as &str);
run(command)?;
Ok(())
}
pub fn fetch(path: &Path, url: &str, refspecs: &[String]) -> Result<(), Error> { pub fn fetch(path: &Path, url: &str, refspecs: &[String]) -> Result<(), Error> {
let mut command = Command::new("git"); let mut command = Command::new("git");
command command

View file

@ -9,6 +9,7 @@ use std::{
time::Duration, time::Duration,
}; };
use anyhow::anyhow;
use axum::extract::FromRef; use axum::extract::FromRef;
use gix::ThreadSafeRepository; use gix::ThreadSafeRepository;
use log::{debug, info}; use log::{debug, info};
@ -18,10 +19,54 @@ use sqlx::{
}; };
use tokio::select; use tokio::select;
use crate::{args::ServerCommand, config::ServerConfig, somehow}; use crate::{args::ServerCommand, config::ServerConfig, git, somehow};
use self::workers::Workers; use self::workers::Workers;
fn open_repo(
path: &Path,
url: &Option<String>,
refspecs: &[String],
) -> somehow::Result<ThreadSafeRepository> {
if path.exists() {
info!("Opening repo at {}", path.display());
Ok(ThreadSafeRepository::open(path)?)
} else if let Some(url) = url {
info!(
"No repo found at {} but a fetch url is configured",
path.display()
);
info!("Creating bare repo");
git::init_bare(path)?;
info!("Fetching HEAD from {url}");
git::fetch_head(path, url)?;
info!("Fetching refs for the first time (this may take a while)");
git::fetch(path, url, refspecs)?;
Ok(ThreadSafeRepository::open(path)?)
} else {
Err(somehow::Error(anyhow!(
"Failed to open repo: No repo found at {} and no fetch url is configured",
path.display()
)))
}
}
fn open_bench_repo(path: &Path) -> somehow::Result<ThreadSafeRepository> {
if path.exists() {
info!("Opening bench repo at {}", path.display());
Ok(ThreadSafeRepository::open(path)?)
} else {
Err(somehow::Error(anyhow!(
"Failed to open bench repo: No repo found at {}",
path.display()
)))
}
}
async fn open_db(path: &Path) -> sqlx::Result<SqlitePool> { async fn open_db(path: &Path) -> sqlx::Result<SqlitePool> {
let options = SqliteConnectOptions::new() let options = SqliteConnectOptions::new()
// https://www.sqlite.org/pragma.html#pragma_journal_mode // https://www.sqlite.org/pragma.html#pragma_journal_mode
@ -77,16 +122,14 @@ impl Server {
command: ServerCommand, command: ServerCommand,
) -> somehow::Result<Self> { ) -> somehow::Result<Self> {
let repo = if let Some(path) = command.repo.as_ref() { let repo = if let Some(path) = command.repo.as_ref() {
info!("Opening repo at {}", path.display()); let repo = open_repo(path, &config.repo_fetch_url, &config.repo_fetch_refspecs)?;
let repo = ThreadSafeRepository::open(path)?;
Some(Repo(Arc::new(repo))) Some(Repo(Arc::new(repo)))
} else { } else {
None None
}; };
let bench_repo = if let Some(path) = command.bench_repo.as_ref() { let bench_repo = if let Some(path) = command.bench_repo.as_ref() {
info!("Opening bench repo at {}", path.display()); let repo = open_bench_repo(path)?;
let repo = ThreadSafeRepository::open(path)?;
Some(BenchRepo(Arc::new(repo))) Some(BenchRepo(Arc::new(repo)))
} else { } else {
None None