| 1 |
|
| 2 |
|
| 3 |
|
| 4 |
|
| 5 |
use anyhow::{Context, Result}; |
| 6 |
use std::path::Path; |
| 7 |
use tokio::process::Command; |
| 8 |
|
| 9 |
const POST_RECEIVE: &str = include_str!("../../hooks/post-receive"); |
| 10 |
|
| 11 |
pub async fn ensure_bare_repo(path: &Path) -> Result<()> { |
| 12 |
if !path.join("HEAD").exists() { |
| 13 |
tokio::fs::create_dir_all(path).await?; |
| 14 |
let out = Command::new("git") |
| 15 |
.args(["init", "--bare", "--initial-branch=main"]) |
| 16 |
.arg(path) |
| 17 |
.output() |
| 18 |
.await |
| 19 |
.context("spawning git init")?; |
| 20 |
anyhow::ensure!( |
| 21 |
out.status.success(), |
| 22 |
"git init --bare failed: {}", |
| 23 |
String::from_utf8_lossy(&out.stderr), |
| 24 |
); |
| 25 |
} |
| 26 |
install_hook(path).await?; |
| 27 |
Ok(()) |
| 28 |
} |
| 29 |
|
| 30 |
async fn install_hook(bare: &Path) -> Result<()> { |
| 31 |
let hook = bare.join("hooks").join("post-receive"); |
| 32 |
tokio::fs::create_dir_all(bare.join("hooks")).await?; |
| 33 |
tokio::fs::write(&hook, POST_RECEIVE).await?; |
| 34 |
#[cfg(unix)] |
| 35 |
{ |
| 36 |
use std::os::unix::fs::PermissionsExt; |
| 37 |
let mut perm = tokio::fs::metadata(&hook).await?.permissions(); |
| 38 |
perm.set_mode(0o755); |
| 39 |
tokio::fs::set_permissions(&hook, perm).await?; |
| 40 |
} |
| 41 |
Ok(()) |
| 42 |
} |
| 43 |
|
| 44 |
pub async fn resolve_ref(bare: &Path, refname: &str) -> Result<String> { |
| 45 |
let out = Command::new("git") |
| 46 |
.arg("--git-dir") |
| 47 |
.arg(bare) |
| 48 |
.args(["rev-parse", refname]) |
| 49 |
.output() |
| 50 |
.await?; |
| 51 |
anyhow::ensure!( |
| 52 |
out.status.success(), |
| 53 |
"git rev-parse {refname} failed: {}", |
| 54 |
String::from_utf8_lossy(&out.stderr), |
| 55 |
); |
| 56 |
Ok(String::from_utf8(out.stdout)?.trim().to_string()) |
| 57 |
} |
| 58 |
|
| 59 |
pub async fn checkout_worktree(bare: &Path, sha: &str, dest: &Path) -> Result<()> { |
| 60 |
if dest.exists() { |
| 61 |
|
| 62 |
return Ok(()); |
| 63 |
} |
| 64 |
tokio::fs::create_dir_all(dest.parent().unwrap()).await?; |
| 65 |
let out = Command::new("git") |
| 66 |
.arg("--git-dir") |
| 67 |
.arg(bare) |
| 68 |
.args(["worktree", "add", "--detach"]) |
| 69 |
.arg(dest) |
| 70 |
.arg(sha) |
| 71 |
.output() |
| 72 |
.await?; |
| 73 |
anyhow::ensure!( |
| 74 |
out.status.success(), |
| 75 |
"git worktree add failed: {}", |
| 76 |
String::from_utf8_lossy(&out.stderr), |
| 77 |
); |
| 78 |
Ok(()) |
| 79 |
} |
| 80 |
|