mirror of
https://github.com/openai/codex.git
synced 2026-05-05 22:01:37 +03:00
## Why PR #13783 moved the `codex.rs` unit tests into `codex_tests.rs`. This applies the same extraction pattern across the rest of `codex-rs/core` so the production modules stay focused on runtime code instead of large inline test blocks. Keeping the tests in sibling files also makes follow-up edits easier to review because product changes no longer have to share a file with hundreds or thousands of lines of test scaffolding. ## What changed - replaced each inline `mod tests { ... }` in `codex-rs/core/src/**` with a path-based module declaration - moved each extracted unit test module into a sibling `*_tests.rs` file, using `mod_tests.rs` for `mod.rs` modules - preserved the existing `cfg(...)` guards and module-local structure so the refactor remains structural rather than behavioral ## Testing - `cargo test -p codex-core --lib` (`1653 passed; 0 failed; 5 ignored`) - `just fix -p codex-core` - `cargo fmt --check` - `cargo shear`
99 lines
3.5 KiB
Rust
99 lines
3.5 KiB
Rust
use crate::config::types::EnvironmentVariablePattern;
|
||
use crate::config::types::ShellEnvironmentPolicy;
|
||
use crate::config::types::ShellEnvironmentPolicyInherit;
|
||
use codex_protocol::ThreadId;
|
||
use std::collections::HashMap;
|
||
use std::collections::HashSet;
|
||
|
||
pub const CODEX_THREAD_ID_ENV_VAR: &str = "CODEX_THREAD_ID";
|
||
|
||
/// Construct an environment map based on the rules in the specified policy. The
|
||
/// resulting map can be passed directly to `Command::envs()` after calling
|
||
/// `env_clear()` to ensure no unintended variables are leaked to the spawned
|
||
/// process.
|
||
///
|
||
/// The derivation follows the algorithm documented in the struct-level comment
|
||
/// for [`ShellEnvironmentPolicy`].
|
||
///
|
||
/// `CODEX_THREAD_ID` is injected when a thread id is provided, even when
|
||
/// `include_only` is set.
|
||
pub fn create_env(
|
||
policy: &ShellEnvironmentPolicy,
|
||
thread_id: Option<ThreadId>,
|
||
) -> HashMap<String, String> {
|
||
populate_env(std::env::vars(), policy, thread_id)
|
||
}
|
||
|
||
fn populate_env<I>(
|
||
vars: I,
|
||
policy: &ShellEnvironmentPolicy,
|
||
thread_id: Option<ThreadId>,
|
||
) -> HashMap<String, String>
|
||
where
|
||
I: IntoIterator<Item = (String, String)>,
|
||
{
|
||
// Step 1 – determine the starting set of variables based on the
|
||
// `inherit` strategy.
|
||
let mut env_map: HashMap<String, String> = match policy.inherit {
|
||
ShellEnvironmentPolicyInherit::All => vars.into_iter().collect(),
|
||
ShellEnvironmentPolicyInherit::None => HashMap::new(),
|
||
ShellEnvironmentPolicyInherit::Core => {
|
||
const CORE_VARS: &[&str] = &[
|
||
"HOME", "LOGNAME", "PATH", "SHELL", "USER", "USERNAME", "TMPDIR", "TEMP", "TMP",
|
||
];
|
||
let allow: HashSet<&str> = CORE_VARS.iter().copied().collect();
|
||
let is_core_var = |name: &str| {
|
||
if cfg!(target_os = "windows") {
|
||
CORE_VARS
|
||
.iter()
|
||
.any(|allowed| allowed.eq_ignore_ascii_case(name))
|
||
} else {
|
||
allow.contains(name)
|
||
}
|
||
};
|
||
vars.into_iter().filter(|(k, _)| is_core_var(k)).collect()
|
||
}
|
||
};
|
||
|
||
// Internal helper – does `name` match **any** pattern in `patterns`?
|
||
let matches_any = |name: &str, patterns: &[EnvironmentVariablePattern]| -> bool {
|
||
patterns.iter().any(|pattern| pattern.matches(name))
|
||
};
|
||
|
||
// Step 2 – Apply the default exclude if not disabled.
|
||
if !policy.ignore_default_excludes {
|
||
let default_excludes = vec![
|
||
EnvironmentVariablePattern::new_case_insensitive("*KEY*"),
|
||
EnvironmentVariablePattern::new_case_insensitive("*SECRET*"),
|
||
EnvironmentVariablePattern::new_case_insensitive("*TOKEN*"),
|
||
];
|
||
env_map.retain(|k, _| !matches_any(k, &default_excludes));
|
||
}
|
||
|
||
// Step 3 – Apply custom excludes.
|
||
if !policy.exclude.is_empty() {
|
||
env_map.retain(|k, _| !matches_any(k, &policy.exclude));
|
||
}
|
||
|
||
// Step 4 – Apply user-provided overrides.
|
||
for (key, val) in &policy.r#set {
|
||
env_map.insert(key.clone(), val.clone());
|
||
}
|
||
|
||
// Step 5 – If include_only is non-empty, keep *only* the matching vars.
|
||
if !policy.include_only.is_empty() {
|
||
env_map.retain(|k, _| matches_any(k, &policy.include_only));
|
||
}
|
||
|
||
// Step 6 – Populate the thread ID environment variable when provided.
|
||
if let Some(thread_id) = thread_id {
|
||
env_map.insert(CODEX_THREAD_ID_ENV_VAR.to_string(), thread_id.to_string());
|
||
}
|
||
|
||
env_map
|
||
}
|
||
|
||
#[cfg(test)]
|
||
#[path = "exec_env_tests.rs"]
|
||
mod tests;
|