1use std::path::Path;
2
3use owo_colors::OwoColorize;
4use rootcause::prelude::ResultExt;
5
6pub fn run() -> rootcause::Result<()> {
7 let zshrc = std::env::var("HOME")
8 .context("error missing HOME environment variable")
9 .map(|home| Path::new(&home).join(".zshrc"))?;
10
11 install_zsh_wrapper_at(&zshrc)?;
12 println!("{} gbm in {}", "Patched".green().bold(), zshrc.display());
13
14 Ok(())
15}
16
17fn install_zsh_wrapper_at(path: &Path) -> rootcause::Result<bool> {
18 let content = std::fs::read_to_string(path)
19 .context("error reading zshrc")
20 .attach_with(|| format!("path={}", path.display()))?;
21
22 if content.lines().any(|line| line.trim() == super::ZSHRC_INSTALL_LINE) {
23 return Ok(false);
24 }
25
26 let mut updated = content;
27 if !updated.is_empty() && !updated.ends_with('\n') {
28 updated.push('\n');
29 }
30 updated.push_str(super::ZSHRC_INSTALL_LINE);
31 updated.push('\n');
32
33 std::fs::write(path, updated)
34 .context("error installing zshrc")
35 .attach_with(|| format!("path={}", path.display()))?;
36
37 Ok(true)
38}
39
40#[cfg(test)]
41mod tests {
42 use test_that::prelude::*;
43
44 use super::*;
45
46 #[test]
47 fn test_install_zsh_wrapper_at_appends_guarded_line_and_is_idempotent() {
48 let dir = tempfile::tempdir().unwrap();
49 let zshrc = dir.path().join(".zshrc");
50 std::fs::write(&zshrc, "source ~/.zshrc.local\n").unwrap();
51
52 assert_that!(install_zsh_wrapper_at(&zshrc), ok(eq(true)));
53 let first = std::fs::read_to_string(&zshrc).unwrap();
54 assert_that!(install_zsh_wrapper_at(&zshrc), ok(eq(false)));
55 let second = std::fs::read_to_string(&zshrc).unwrap();
56
57 assert_that!(first, eq(second));
58 assert_that!(
59 first,
60 eq(format!("source ~/.zshrc.local\n{}\n", super::super::ZSHRC_INSTALL_LINE))
61 );
62 assert_that!(first.matches(super::super::ZSHRC_INSTALL_LINE).count(), eq(1));
63 }
64
65 #[test]
66 fn test_install_zsh_wrapper_at_fails_when_zshrc_is_missing() {
67 let dir = tempfile::tempdir().unwrap();
68 let zshrc = dir.path().join(".zshrc");
69
70 assert_that!(
71 install_zsh_wrapper_at(&zshrc),
72 err(displays_as(contains_substring("error reading zshrc")))
73 );
74 }
75}