git_xcrypt/commands/process.rs
1//! `git-xcrypt process` — the entry point git itself calls.
2//!
3//! Registered by `init` as `filter.git-xcrypt.process`. Everything it writes to
4//! `stdout` is protocol; diagnostics go to `stderr` and nowhere else.
5
6use std::io;
7
8use crate::Result;
9use crate::commands::filter::{self, Context};
10use crate::git::repo::Repo;
11
12/// Serves git's filter protocol until the stream closes.
13///
14/// # Errors
15///
16/// [`crate::Error::Config`] when the repository or `.git-xcrypt` cannot be read,
17/// [`crate::Error::Io`] on a broken pipe.
18pub fn run() -> Result<()> {
19 let repo = Repo::discover_from_cwd()?;
20 let mut context = Context::load(&repo)?;
21
22 let mut input = io::stdin().lock();
23 // `BufWriter`, not the bare lock: `StdoutLock` is line buffered, and
24 // ciphertext is uniformly random, so roughly one byte in 256 is `\n` and
25 // would force a syscall. This is the path whose entire justification is the
26 // 22× measurement. `pktline::write_flush` still forces the real flush at
27 // every point the protocol requires one.
28 let mut output = io::BufWriter::new(io::stdout().lock());
29 filter::run(&mut context, &mut input, &mut output)
30}