agcodex_core/
util.rs

1use std::path::Path;
2use std::time::Duration;
3
4use rand::Rng;
5
6const INITIAL_DELAY_MS: u64 = 200;
7const BACKOFF_FACTOR: f64 = 2.0;
8
9pub(crate) fn backoff(attempt: u64) -> Duration {
10    let exp = BACKOFF_FACTOR.powi(attempt.saturating_sub(1) as i32);
11    let base = (INITIAL_DELAY_MS as f64 * exp) as u64;
12    let jitter = rand::rng().random_range(0.9..1.1);
13    Duration::from_millis((base as f64 * jitter) as u64)
14}
15
16/// Return `true` if the project folder specified by the `Config` is inside a
17/// Git repository.
18///
19/// The check walks up the directory hierarchy looking for a `.git` file or
20/// directory (note `.git` can be a file that contains a `gitdir` entry). This
21/// approach does **not** require the `git` binary or the `git2` crate and is
22/// therefore fairly lightweight.
23///
24/// Note that this does **not** detect *work‑trees* created with
25/// `git worktree add` where the checkout lives outside the main repository
26/// directory. If you need Codex to work from such a checkout simply pass the
27/// `--allow-no-git-exec` CLI flag that disables the repo requirement.
28pub fn is_inside_git_repo(base_dir: &Path) -> bool {
29    let mut dir = base_dir.to_path_buf();
30
31    loop {
32        if dir.join(".git").exists() {
33            return true;
34        }
35
36        // Pop one component (go up one directory).  `pop` returns false when
37        // we have reached the filesystem root.
38        if !dir.pop() {
39            break;
40        }
41    }
42
43    false
44}