mirror of
https://github.com/openai/codex.git
synced 2026-10-20 17:38:45 +00:00
## What changed - Add the experimental `worktrees` feature and a shared `--worktree` flag for new and forked `codex exec` sessions. - Create each enabled session in a managed Git worktree, use that checkout as the session working directory, and bind the checkout to the new thread. - Share the configured worktree pool with Desktop while leaving automatic cleanup disabled for CLI allocations. - Reject unsupported commands, remote execution, ignored user configuration, ephemeral sessions, and use without the feature enabled before allocating a worktree. ## Testing - Cover flag placement and inheritance, supported and rejected command combinations, worktree allocation and thread ownership, configuration gating, and compatibility with existing worktree-backed sessions. GitOrigin-RevId: 011ff4639b09e8992c50d7b823df23e71798670e
93 lines
3.2 KiB
Rust
93 lines
3.2 KiB
Rust
//! Resolves managed-worktree settings shared with Desktop.
|
|
//! CLI allocation uses the same root without enabling automatic cleanup.
|
|
|
|
use anyhow::Context;
|
|
use anyhow::Result;
|
|
use anyhow::bail;
|
|
use serde_json::Value;
|
|
use std::collections::HashMap;
|
|
use std::path::Path;
|
|
use std::path::PathBuf;
|
|
|
|
const WORKTREE_ROOT: &str = "git-worktree-root";
|
|
const AUTO_CLEANUP: &str = "worktree-auto-cleanup-enabled";
|
|
const KEEP_COUNT: &str = "worktree-keep-count";
|
|
|
|
pub const DEFAULT_WORKTREE_KEEP_COUNT: usize = 15;
|
|
|
|
/// Effective host-local settings for managed worktrees.
|
|
#[derive(Clone, Debug, PartialEq, Eq)]
|
|
pub struct WorktreeSettings {
|
|
pub root: PathBuf,
|
|
pub auto_cleanup_enabled: bool,
|
|
pub keep_count: usize,
|
|
}
|
|
|
|
impl WorktreeSettings {
|
|
/// Shares Desktop's allocation root while leaving CLI cleanup disabled.
|
|
pub fn for_cli(codex_home: &Path, desktop: Option<&HashMap<String, Value>>) -> Result<Self> {
|
|
let desktop = desktop
|
|
.and_then(|settings| settings.get(WORKTREE_ROOT))
|
|
.map(|root| HashMap::from([(WORKTREE_ROOT.to_owned(), root.clone())]));
|
|
Ok(Self {
|
|
auto_cleanup_enabled: false,
|
|
..Self::from_desktop_config(codex_home, desktop.as_ref())?
|
|
})
|
|
}
|
|
|
|
/// Resolves existing `[desktop]` values without introducing another config format.
|
|
pub fn from_desktop_config(
|
|
codex_home: &Path,
|
|
desktop: Option<&HashMap<String, Value>>,
|
|
) -> Result<Self> {
|
|
let root = match desktop.and_then(|settings| settings.get(WORKTREE_ROOT)) {
|
|
None | Some(Value::Null) => codex_home.join("worktrees"),
|
|
Some(value) => {
|
|
let configured = value
|
|
.as_str()
|
|
.context("desktop.git-worktree-root must be a string")?
|
|
.trim();
|
|
if configured.is_empty() {
|
|
codex_home.join("worktrees")
|
|
} else {
|
|
let path = PathBuf::from(configured);
|
|
if !path.is_absolute() {
|
|
bail!("desktop.git-worktree-root must be an absolute path");
|
|
}
|
|
path
|
|
}
|
|
}
|
|
};
|
|
|
|
let auto_cleanup_enabled = desktop
|
|
.and_then(|settings| settings.get(AUTO_CLEANUP))
|
|
.map(|value| {
|
|
value
|
|
.as_bool()
|
|
.context("desktop.worktree-auto-cleanup-enabled must be a boolean")
|
|
})
|
|
.transpose()?
|
|
.unwrap_or(true);
|
|
|
|
let keep_count = desktop
|
|
.and_then(|settings| settings.get(KEEP_COUNT))
|
|
.map(|value| {
|
|
let count = value
|
|
.as_u64()
|
|
.context("desktop.worktree-keep-count must be a positive integer")?;
|
|
if count == 0 {
|
|
bail!("desktop.worktree-keep-count must be a positive integer");
|
|
}
|
|
usize::try_from(count).context("desktop.worktree-keep-count is too large")
|
|
})
|
|
.transpose()?
|
|
.unwrap_or(DEFAULT_WORKTREE_KEEP_COUNT);
|
|
|
|
Ok(Self {
|
|
root: dunce::simplified(&root).to_path_buf(),
|
|
auto_cleanup_enabled,
|
|
keep_count,
|
|
})
|
|
}
|
|
}
|