.reveal()
.context("failed to resolve GitHub token")?;
- tracing::info!(url = %mirror.url, "pushing to mirror");
- repo.push_to_mirror(&mirror, token)?;
+ // Parse pushed refs from stdin. Each line is:
+ // <old-sha> <new-sha> <refname>
+ // Only push refs that were actually updated (new sha is not all zeros).
+ let stdin = io::stdin();
+ let mut refs: Vec<String> = Vec::new();
+ for line in stdin.lines() {
+ let line = line.map_err(|e| miette!("failed to read hook stdin: {e}"))?;
+ let parts: Vec<&str> = line.split_whitespace().collect();
+ if parts.len() != 3 {
+ continue;
+ }
+ let new_sha = parts[1];
+ if new_sha == "0000000000000000000000000000000000000000" {
+ continue;
+ }
+ refs.push(parts[2].to_string());
+ }
+
+ if refs.is_empty() {
+ return Ok(());
+ }
+
+ let ref_slices: Vec<&str> = refs.iter().map(|s| s.as_str()).collect();
+ tracing::info!(url = %mirror.url, refs = ?ref_slices, "pushing to mirror");
+ repo.push_to_mirror(&mirror, token, &ref_slices)?;
tracing::info!(url = %mirror.url, "mirror push complete");
Ok(())
}
/// but it remains visible in `/proc/<pid>/environ` to anything running
/// as the same uid for the lifetime of the push. Acceptable today
/// (single-user container, no CI runner yet); revisit when CI lands.
- pub fn push_to_mirror(&self, mirror: &MirrorConfig, token: &str) -> crate::Result<()> {
+ pub fn push_to_mirror(&self, mirror: &MirrorConfig, token: &str, refs: &[&str]) -> crate::Result<()> {
+ let mut args = vec!["push", "--porcelain", &mirror.url];
+ args.extend(refs);
+
let status = self
- .git(&["push", "--porcelain", &mirror.url, "main"])
+ .git(&args)
.env("GIT_CONFIG_COUNT", "1")
.env("GIT_CONFIG_KEY_0", "http.extraHeader")
.env(
let mirror = MirrorConfig {
url: format!("file://{}", target.display()),
};
- repo.push_to_mirror(&mirror, "ignored-for-file-url")
+ repo.push_to_mirror(&mirror, "ignored-for-file-url", &["main"])
.expect("push should succeed");
assert_eq!(rev_parse(&source, "main"), rev_parse(&target, "main"));
let mirror = MirrorConfig {
url: "file:///nonexistent/quire-test/target.git".to_string(),
};
- let err = repo.push_to_mirror(&mirror, "x").unwrap_err();
+ let err = repo.push_to_mirror(&mirror, "x", &["main"]).unwrap_err();
assert!(
matches!(err, crate::Error::Git(_)),
"expected Git error, got {err:?}"