]> quire.kejadlen.dev Git - quire.git/commitdiff
Build git 2.54 from source and add hook subcommand
authorAlpha Chen <alpha@kejadlen.dev>
Sat, 25 Apr 2026 04:44:53 +0000 (04:44 +0000)
committerAlpha Chen <alpha@kejadlen.dev>
Sat, 25 Apr 2026 13:45:59 +0000 (06:45 -0700)
Debian bookworm ships git 2.39 but we need 2.54+ for
hook.<name>.command config support, which lets quire register
hooks via git config instead of writing shim scripts to disk.

The hook subcommand is a no-op that logs invocations — enough to
verify the dispatch path works end-to-end.

Assisted-by: GLM-5.1 via pi
Dockerfile
src/bin/quire/commands/hook.rs [new file with mode: 0644]
src/bin/quire/commands/mod.rs
src/bin/quire/main.rs

index fc747699ad7cfbada0fb56e444858264ce58737b..7923e3bd0c2d2c93c7edde3f4b3de0872efae829 100644 (file)
@@ -1,4 +1,32 @@
-# Build stage.
+# Git build stage.
+#
+# Debian bookworm ships git 2.39, but we need 2.54+ for hook.<name>.command
+# config support. This lets quire register hooks via git config instead of
+# writing shim scripts to disk — the hook dispatches directly into the
+# quire binary as `quire hook <name>`.
+ARG GIT_VERSION=2.54.0
+FROM debian:bookworm-slim AS git-builder
+
+RUN apt-get update \
+    && apt-get install -y --no-install-recommends \
+        ca-certificates \
+        curl \
+        gcc \
+        gettext \
+        libcurl4-openssl-dev \
+        libexpat1-dev \
+        libssl-dev \
+        libz-dev \
+        make \
+    && rm -rf /var/lib/apt/lists/*
+
+RUN curl -fsSL https://github.com/git/git/archive/refs/tags/v${GIT_VERSION}.tar.gz \
+    | tar xz \
+    && cd git-${GIT_VERSION} \
+    && make -j$(nproc) prefix=/usr/local NO_TCLTK=1 NO_GETTEXT= \
+    && make prefix=/usr/local install
+
+# Quire build stage.
 FROM rust:1.88-bookworm AS builder
 
 WORKDIR /usr/src/quire
@@ -12,10 +40,13 @@ FROM debian:bookworm-slim
 
 RUN apt-get update \
     && apt-get install -y --no-install-recommends \
-        git \
         ca-certificates \
+        libcurl4 \
+        libexpat1 \
     && rm -rf /var/lib/apt/lists/*
 
+COPY --from=git-builder /usr/local/bin/git /usr/local/bin/git
+COPY --from=git-builder /usr/local/libexec/git-core/ /usr/local/libexec/git-core/
 COPY --from=builder /usr/local/cargo/bin/quire /usr/local/bin/quire
 
 # Volume layout per PLAN.md. Ownership is set on the host; the container
diff --git a/src/bin/quire/commands/hook.rs b/src/bin/quire/commands/hook.rs
new file mode 100644 (file)
index 0000000..17c5fb2
--- /dev/null
@@ -0,0 +1,6 @@
+use miette::Result;
+
+pub async fn run(hook_name: &str) -> Result<()> {
+    tracing::info!(hook = %hook_name, "hook invoked");
+    Ok(())
+}
index 003cac0fb2c3ec060937d0d96c984806543edf82..68ed5a047587d23f156a817a380bc83340fcd3fc 100644 (file)
@@ -1,2 +1,3 @@
 pub mod exec;
+pub mod hook;
 pub mod serve;
index 684258924c89c2c1e21fa41e881ee50d8381ec58..5ab7114434c71d84f74f6a8caa9e02d40373da1c 100644 (file)
@@ -37,6 +37,12 @@ enum Commands {
         /// Pass as a single argument: quire exec "git-receive-pack '/foo.git'"
         command: Vec<String>,
     },
+
+    /// Invoked by git hooks configured via hook.<name>.command.
+    Hook {
+        /// The hook name (e.g. pre-receive, post-receive).
+        hook_name: String,
+    },
 }
 
 #[tokio::main]
@@ -63,6 +69,7 @@ async fn main() -> Result<()> {
     match command {
         Commands::Serve => commands::serve::run(&config).await?,
         Commands::Exec { command } => commands::exec::run(&config, command).await?,
+        Commands::Hook { hook_name } => commands::hook::run(&hook_name).await?,
     }
 
     Ok(())