thoughts_tool/git/
shell_fetch.rs1use anyhow::{Context, Result, bail};
2use std::path::Path;
3use std::process::{Command, Stdio};
4
5pub fn build_fetch_command(repo_path: &Path, remote: &str) -> Command {
7 let mut cmd = Command::new("git");
8 cmd.current_dir(repo_path).arg("fetch").arg(remote);
9 cmd
10}
11
12pub fn fetch(repo_path: &Path, remote: &str) -> Result<()> {
14 which::which("git").context("git executable not found in PATH")?;
15
16 let mut cmd = build_fetch_command(repo_path, remote);
17 let status = cmd
18 .stdout(Stdio::null())
19 .stderr(Stdio::inherit())
20 .status()
21 .with_context(|| {
22 format!(
23 "Failed to spawn git fetch for remote '{}' in '{}'",
24 remote,
25 repo_path.display()
26 )
27 })?;
28
29 if !status.success() {
30 bail!(
31 "git fetch failed for remote '{}' in '{}' with exit code {:?}",
32 remote,
33 repo_path.display(),
34 status.code()
35 );
36 }
37 Ok(())
38}
39
40#[cfg(test)]
41mod tests {
42 use super::*;
43 use std::path::Path;
44
45 #[test]
46 fn build_fetch_cmd_has_expected_args() {
47 let cmd = build_fetch_command(Path::new("/tmp/repo"), "origin");
48 let args: Vec<String> = cmd
49 .get_args()
50 .map(|s| s.to_string_lossy().into_owned())
51 .collect();
52 assert_eq!(args, vec!["fetch", "origin"]);
53 assert_eq!(cmd.get_current_dir(), Some(Path::new("/tmp/repo")));
54 }
55}