If a global git `post-commit` hook is not already set up for tracedecay, interactively asks the user whether to install one. Silently succeeds if the hook is already present, if stdin is not a terminal, or if the user declines.
(tracedecay_bin: &str)
| 1489 | /// the hook is already present, if stdin is not a terminal, or if the user |
| 1490 | /// declines. |
| 1491 | pub fn offer_git_post_commit_hook(tracedecay_bin: &str) { |
| 1492 | let Some(home) = home_dir() else { return }; |
| 1493 | |
| 1494 | // Determine the global hooks directory by reading core.hooksPath from |
| 1495 | // the global gitconfig file(s). Falls back to ~/.config/git/hooks/. |
| 1496 | let hooks_dir = read_global_hooks_path(&home); |
| 1497 | |
| 1498 | let (hooks_dir, need_set_hookspath) = match hooks_dir { |
| 1499 | Some(dir) => (dir, false), |
| 1500 | None => (home.join(".config").join("git").join("hooks"), true), |
| 1501 | }; |
| 1502 | |
| 1503 | let hook_path = hooks_dir.join("post-commit"); |
| 1504 | |
| 1505 | // Check if already installed. |
| 1506 | if hook_path.exists() { |
| 1507 | if let Ok(contents) = std::fs::read_to_string(&hook_path) { |
| 1508 | if contents.contains(HOOK_MARKER) { |
| 1509 | eprintln!(" Global git post-commit hook already contains tracedecay, skipping"); |
| 1510 | return; |
| 1511 | } |
| 1512 | } |
| 1513 | } |
| 1514 | |
| 1515 | // Only prompt on a real terminal. |
| 1516 | if !atty_stdin() { |
| 1517 | return; |
| 1518 | } |
| 1519 | |
| 1520 | eprintln!(); |
| 1521 | eprint!( |
| 1522 | "Install a global git post-commit hook to auto-run \x1b[1mtracedecay sync\x1b[0m after each commit? [y/N] " |
| 1523 | ); |
| 1524 | |
| 1525 | let mut answer = String::new(); |
| 1526 | if std::io::stdin().read_line(&mut answer).is_err() { |
| 1527 | return; |
| 1528 | } |
| 1529 | if !matches!(answer.trim(), "y" | "Y" | "yes" | "Yes") { |
| 1530 | eprintln!(" Skipped git post-commit hook"); |
| 1531 | return; |
| 1532 | } |
| 1533 | |
| 1534 | // Create the hooks directory if needed. |
| 1535 | if let Err(e) = std::fs::create_dir_all(&hooks_dir) { |
| 1536 | eprintln!( |
| 1537 | " \x1b[31m✘\x1b[0m Failed to create {}: {e}", |
| 1538 | hooks_dir.display() |
| 1539 | ); |
| 1540 | return; |
| 1541 | } |
| 1542 | |
| 1543 | // If no global hooksPath was configured, set it in ~/.gitconfig. |
| 1544 | if need_set_hookspath { |
| 1545 | let gitconfig_path = home.join(".gitconfig"); |
| 1546 | if let Err(msg) = set_global_hooks_path(&gitconfig_path, &hooks_dir) { |
| 1547 | eprintln!(" \x1b[31m✘\x1b[0m {msg} — hook not installed"); |
| 1548 | return; |
no test coverage detected