mirror of
https://github.com/openai/codex.git
synced 2026-09-04 15:08:45 +00:00
fixes
This commit is contained in:
@@ -44,6 +44,9 @@ use crate::invocation::ExtractHeredocError;
|
||||
/// surface.
|
||||
pub const CODEX_CORE_APPLY_PATCH_ARG1: &str = "--codex-run-as-apply-patch";
|
||||
|
||||
/// Enables CRLF preservation for the standalone `apply_patch` command.
|
||||
pub const APPLY_PATCH_PRESERVE_CRLF_ARG: &str = "--preserve-crlf";
|
||||
|
||||
/// Controls optional behavior when parsing or applying a patch.
|
||||
#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
|
||||
pub struct ApplyPatchOptions {
|
||||
|
||||
@@ -442,8 +442,8 @@ fn parse_update_file_chunk(
|
||||
match line_contents.chars().next() {
|
||||
None => {
|
||||
// Interpret this as an empty line.
|
||||
chunk.old_lines.push(String::new());
|
||||
chunk.new_lines.push(String::new());
|
||||
chunk.old_lines.push(line.to_string());
|
||||
chunk.new_lines.push(line.to_string());
|
||||
}
|
||||
Some(' ') => {
|
||||
chunk.old_lines.push(line[1..].to_string());
|
||||
@@ -587,6 +587,34 @@ fn test_update_file_chunk() {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_update_file_chunk_preserves_crlf_for_bare_empty_context_line() {
|
||||
assert_eq!(
|
||||
parse_update_file_chunk(
|
||||
&["@@\r", " before\r", "\r", " after\r", "*** End Patch\r"],
|
||||
/*line_number*/ 123,
|
||||
/*allow_missing_context*/ false,
|
||||
),
|
||||
Ok((
|
||||
UpdateFileChunk {
|
||||
change_context: None,
|
||||
old_lines: vec![
|
||||
"before\r".to_string(),
|
||||
"\r".to_string(),
|
||||
"after\r".to_string(),
|
||||
],
|
||||
new_lines: vec![
|
||||
"before\r".to_string(),
|
||||
"\r".to_string(),
|
||||
"after\r".to_string(),
|
||||
],
|
||||
is_end_of_file: false,
|
||||
},
|
||||
4,
|
||||
))
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_parse_patch() {
|
||||
assert_eq!(
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
use std::io::Read;
|
||||
use std::io::Write;
|
||||
|
||||
const PRESERVE_CRLF_FLAG: &str = "--preserve-crlf";
|
||||
|
||||
pub fn main() -> ! {
|
||||
let exit_code = run_main();
|
||||
std::process::exit(exit_code);
|
||||
@@ -17,7 +15,7 @@ pub fn run_main() -> i32 {
|
||||
let _argv0 = args.next();
|
||||
let first_arg = args.next();
|
||||
let (options, patch_arg) = match first_arg {
|
||||
Some(arg) if arg.to_str() == Some(PRESERVE_CRLF_FLAG) => {
|
||||
Some(arg) if arg == crate::APPLY_PATCH_PRESERVE_CRLF_ARG => {
|
||||
(crate::ApplyPatchOptions::preserve_crlf(), args.next())
|
||||
}
|
||||
patch_arg => (crate::ApplyPatchOptions::default(), patch_arg),
|
||||
|
||||
@@ -4,6 +4,7 @@ use std::future::Future;
|
||||
use std::path::Path;
|
||||
use std::path::PathBuf;
|
||||
|
||||
use codex_apply_patch::APPLY_PATCH_PRESERVE_CRLF_ARG;
|
||||
use codex_apply_patch::CODEX_CORE_APPLY_PATCH_ARG1;
|
||||
use codex_exec_server::CODEX_FS_HELPER_ARG1;
|
||||
use codex_install_context::InstallContext;
|
||||
@@ -100,7 +101,15 @@ pub fn arg0_dispatch() -> Option<Arg0PathEntryGuard> {
|
||||
codex_exec_server::run_fs_helper_main();
|
||||
}
|
||||
if argv1 == CODEX_CORE_APPLY_PATCH_ARG1 {
|
||||
let patch_arg = args.next().and_then(|s| s.to_str().map(str::to_owned));
|
||||
let first_arg = args.next();
|
||||
let (options, patch_arg) = match first_arg {
|
||||
Some(arg) if arg == APPLY_PATCH_PRESERVE_CRLF_ARG => (
|
||||
codex_apply_patch::ApplyPatchOptions::preserve_crlf(),
|
||||
args.next(),
|
||||
),
|
||||
patch_arg => (codex_apply_patch::ApplyPatchOptions::default(), patch_arg),
|
||||
};
|
||||
let patch_arg = patch_arg.and_then(|s| s.to_str().map(str::to_owned));
|
||||
let exit_code = match patch_arg {
|
||||
Some(patch_arg) => {
|
||||
let mut stdout = std::io::stdout();
|
||||
@@ -116,8 +125,9 @@ pub fn arg0_dispatch() -> Option<Arg0PathEntryGuard> {
|
||||
Ok(runtime) => runtime,
|
||||
Err(_) => std::process::exit(1),
|
||||
};
|
||||
match runtime.block_on(codex_apply_patch::apply_patch(
|
||||
match runtime.block_on(codex_apply_patch::apply_patch_with_options(
|
||||
&patch_arg,
|
||||
options,
|
||||
&cwd,
|
||||
&mut stdout,
|
||||
&mut stderr,
|
||||
|
||||
@@ -44,6 +44,31 @@ fn test_standalone_exec_cli_can_use_apply_patch() -> anyhow::Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_standalone_exec_cli_can_preserve_crlf() -> anyhow::Result<()> {
|
||||
let tmp = tempdir()?;
|
||||
let relative_path = "source.txt";
|
||||
let absolute_path = tmp.path().join(relative_path);
|
||||
fs::write(&absolute_path, "original content\r\n")?;
|
||||
|
||||
Command::new(codex_utils_cargo_bin::cargo_bin("codex-exec")?)
|
||||
.arg(CODEX_CORE_APPLY_PATCH_ARG1)
|
||||
.arg("--preserve-crlf")
|
||||
.arg(
|
||||
"*** Begin Patch\r\n*** Update File: source.txt\r\n@@\r\n-original content\r\n+modified by apply_patch\r\n*** End Patch\r\n",
|
||||
)
|
||||
.current_dir(tmp.path())
|
||||
.assert()
|
||||
.success()
|
||||
.stdout("Success. Updated the following files:\nM source.txt\n")
|
||||
.stderr(predicates::str::is_empty());
|
||||
assert_eq!(
|
||||
fs::read_to_string(absolute_path)?,
|
||||
"modified by apply_patch\r\n"
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "windows"))]
|
||||
#[tokio::test(flavor = "multi_thread", worker_threads = 4)]
|
||||
async fn test_apply_patch_tool() -> anyhow::Result<()> {
|
||||
|
||||
Reference in New Issue
Block a user