Skip to main content

carry_hooks_path

Function carry_hooks_path 

Source
pub fn carry_hooks_path(primary: &Path, worktree: &Path) -> HooksPath
Expand description

Bind worktree to the hooks directory of its own tree, when the repository tracks one and git would otherwise run another worktree’s.

primary is the primary checkout, whose effective core.hooksPath is the repository’s policy. Never fails: the worst outcome is a worktree left as git left it, reported. The primary checkout itself is answered with what it runs and never changed.

use std::process::Command;
use majordomus_cli::worktree::{carry_hooks_path, HooksPath};

let dir = tempfile::tempdir().unwrap();
let r = dir.path().join("r");
let wt = dir.path().join("r-wt").join("x");
let git = |cwd: &std::path::Path, args: &[&str]| {
    assert!(Command::new("git").arg("-C").arg(cwd).args(args).status().unwrap().success());
};
std::fs::create_dir_all(r.join(".githooks")).unwrap();
std::fs::write(r.join(".githooks/pre-commit"), "#!/bin/sh\n").unwrap();
git(dir.path(), &["init", "-q", r.to_str().unwrap()]);
git(&r, &["add", "."]);
git(&r, &["-c", "user.name=t", "-c", "user.email=t@t", "commit", "-qm", "hooks"]);
// The value that sent every worktree to the primary's hooks: absolute, shared.
let primary_hooks = r.join(".githooks");
git(&r, &["config", "core.hooksPath", primary_hooks.to_str().unwrap()]);
git(&r, &["worktree", "add", "-q", "-b", "x", wt.to_str().unwrap()]);

match carry_hooks_path(&r, &wt) {
    HooksPath::Set { path, .. } => assert!(path.ends_with("r-wt/x/.githooks")),
    other => panic!("expected the worktree's own hooks to be set, got {other:?}"),
}
// A second call finds it done.
assert!(matches!(carry_hooks_path(&r, &wt), HooksPath::Own { .. }));