mirror of
https://github.com/openai/codex.git
synced 2026-05-24 04:54:52 +00:00
## Why `codex-utils-pty` and `codex-windows-sandbox` were the remaining crates in `codex-rs` that still overrode the workspace's Rust 2024 edition. Moving them forward in a separate PR keeps the baseline edition update isolated from the follow-on Bazel clippy workflow in #15955, while making linting and formatting behavior consistent with the rest of the workspace. This PR also needs Cargo and Bazel to agree on the edition for `codex-windows-sandbox`. Without the Bazel-side sync, the experimental Bazel app-server builds fail once they compile `windows-sandbox-rs`. ## What changed - switch `codex-rs/utils/pty` and `codex-rs/windows-sandbox-rs` to `edition = "2024"` - update `codex-utils-pty` callsites and tests to use the collapsed `if let` form that Clippy expects under the new edition - fix the Rust 2024 fallout in `windows-sandbox-rs`, including the reserved `gen` identifier, `unsafe extern` requirements, and new Clippy findings that surfaced under the edition bump - keep the edition bump separate from a larger unsafe cleanup by temporarily allowing `unsafe_op_in_unsafe_fn` in the Windows entrypoint modules that now report it under Rust 2024 - update `codex-rs/windows-sandbox-rs/BUILD.bazel` to `crate_edition = "2024"` so Bazel compiles the crate with the same edition as Cargo --- [//]: # (BEGIN SAPLING FOOTER) Stack created with [Sapling](https://sapling-scm.com). Best reviewed with [ReviewStack](https://reviewstack.dev/openai/codex/pull/15954). * #15976 * #15955 * __->__ #15954
92 lines
2.7 KiB
Rust
92 lines
2.7 KiB
Rust
use std::fs::OpenOptions;
|
|
use std::io::Write;
|
|
use std::path::Path;
|
|
use std::path::PathBuf;
|
|
use std::sync::OnceLock;
|
|
|
|
use codex_utils_string::take_bytes_at_char_boundary;
|
|
|
|
const LOG_COMMAND_PREVIEW_LIMIT: usize = 200;
|
|
pub const LOG_FILE_NAME: &str = "sandbox.log";
|
|
|
|
fn exe_label() -> &'static str {
|
|
static LABEL: OnceLock<String> = OnceLock::new();
|
|
LABEL.get_or_init(|| {
|
|
std::env::current_exe()
|
|
.ok()
|
|
.and_then(|p| p.file_name().map(|n| n.to_string_lossy().to_string()))
|
|
.unwrap_or_else(|| "proc".to_string())
|
|
})
|
|
}
|
|
|
|
fn preview(command: &[String]) -> String {
|
|
let joined = command.join(" ");
|
|
if joined.len() <= LOG_COMMAND_PREVIEW_LIMIT {
|
|
joined
|
|
} else {
|
|
take_bytes_at_char_boundary(&joined, LOG_COMMAND_PREVIEW_LIMIT).to_string()
|
|
}
|
|
}
|
|
|
|
fn log_file_path(base_dir: &Path) -> Option<PathBuf> {
|
|
if base_dir.is_dir() {
|
|
Some(base_dir.join(LOG_FILE_NAME))
|
|
} else {
|
|
None
|
|
}
|
|
}
|
|
|
|
fn append_line(line: &str, base_dir: Option<&Path>) {
|
|
if let Some(dir) = base_dir
|
|
&& let Some(path) = log_file_path(dir)
|
|
&& let Ok(mut f) = OpenOptions::new().create(true).append(true).open(path)
|
|
{
|
|
let _ = writeln!(f, "{line}");
|
|
}
|
|
}
|
|
|
|
pub fn log_start(command: &[String], base_dir: Option<&Path>) {
|
|
let p = preview(command);
|
|
log_note(&format!("START: {p}"), base_dir);
|
|
}
|
|
|
|
pub fn log_success(command: &[String], base_dir: Option<&Path>) {
|
|
let p = preview(command);
|
|
log_note(&format!("SUCCESS: {p}"), base_dir);
|
|
}
|
|
|
|
pub fn log_failure(command: &[String], detail: &str, base_dir: Option<&Path>) {
|
|
let p = preview(command);
|
|
log_note(&format!("FAILURE: {p} ({detail})"), base_dir);
|
|
}
|
|
|
|
// Debug logging helper. Emits only when SBX_DEBUG=1 to avoid noisy logs.
|
|
pub fn debug_log(msg: &str, base_dir: Option<&Path>) {
|
|
if std::env::var("SBX_DEBUG").ok().as_deref() == Some("1") {
|
|
append_line(&format!("DEBUG: {msg}"), base_dir);
|
|
eprintln!("{msg}");
|
|
}
|
|
}
|
|
|
|
// Unconditional note logging to sandbox.log
|
|
pub fn log_note(msg: &str, base_dir: Option<&Path>) {
|
|
let ts = chrono::Local::now().format("%Y-%m-%d %H:%M:%S%.3f");
|
|
append_line(&format!("[{ts} {}] {}", exe_label(), msg), base_dir);
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use super::*;
|
|
|
|
#[test]
|
|
fn preview_does_not_panic_on_utf8_boundary() {
|
|
// Place a 4-byte emoji such that naive (byte-based) truncation would split it.
|
|
let prefix = "x".repeat(LOG_COMMAND_PREVIEW_LIMIT - 1);
|
|
let command = vec![format!("{prefix}😀")];
|
|
let result = std::panic::catch_unwind(|| preview(&command));
|
|
assert!(result.is_ok());
|
|
let previewed = result.unwrap();
|
|
assert!(previewed.len() <= LOG_COMMAND_PREVIEW_LIMIT);
|
|
}
|
|
}
|