(project: &Path, args: &[&str])
| 55 | } |
| 56 | |
| 57 | fn git(project: &Path, args: &[&str]) { |
| 58 | let git = crate::common::git_program(); |
| 59 | // Retry a transient spawn ENOENT under heavy parallel load. |
| 60 | let mut last_err: Option<std::io::Error> = None; |
| 61 | let mut output = None; |
| 62 | for attempt in 0..5 { |
| 63 | match std::process::Command::new(&git) |
| 64 | .args(args) |
| 65 | .current_dir(project) |
| 66 | .output() |
| 67 | { |
| 68 | Ok(out) => { |
| 69 | output = Some(out); |
| 70 | break; |
| 71 | } |
| 72 | Err(e) if e.kind() == std::io::ErrorKind::NotFound && attempt < 4 => { |
| 73 | last_err = Some(e); |
| 74 | std::thread::sleep(Duration::from_millis(20 * (attempt + 1))); |
| 75 | } |
| 76 | Err(e) => panic!("git {args:?} should run (program {git:?}): {e}"), |
| 77 | } |
| 78 | } |
| 79 | let output = |
| 80 | output.unwrap_or_else(|| panic!("git {args:?} should run after retries: {last_err:?}")); |
| 81 | assert!( |
| 82 | output.status.success(), |
| 83 | "git {:?} failed\nstdout:\n{}\nstderr:\n{}", |
| 84 | args, |
| 85 | String::from_utf8_lossy(&output.stdout), |
| 86 | String::from_utf8_lossy(&output.stderr) |
| 87 | ); |
| 88 | } |
| 89 | |
| 90 | fn tool_status_server_tool_calls(home: &Path, project: &Path) -> u64 { |
| 91 | let project_arg = project.to_string_lossy().to_string(); |
no test coverage detected