Skip to main content

max / makenotwork

2.4 KB · 80 lines History Blame Raw
1 //! Thin shell wrappers around `git`. We avoid pulling in libgit2 — the daemon
2 //! shells out for `cargo build` and friends anyway, and `git` is always on the
3 //! MakeMachine.
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 // Pre-existing worktree (re-trigger of same sha). Idempotent — nothing to do.
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