pub fn apply_diff(
root: impl AsRef<Path>,
patch: &str,
) -> Result<ApplyDiffReport, ApplyDiffError>Expand description
Applies a complete patch to files beneath root.
The patch must use *** Begin Patch and *** End Patch, with one or more
*** Add File:, *** Update File:, or *** Delete File: blocks. Update
blocks may include *** Move to: immediately after their file header.
Each logical file is independent: failures do not prevent unrelated files from committing. All blocks connected through the same paths are first applied in memory and then committed together, so a failed file is never left partially edited.
Paths must be non-empty and relative, may not contain . or .., and may
not traverse symbolic links. Existing files must be regular UTF-8 files.
Missing parent directories for added or moved files are created as needed.
Updates are installed with atomic replacement on Linux, macOS, and Windows.
Overlapping paths are serialized within this process. Before each commit,
the current file is compared with the snapshot used for planning; an
observed external modification becomes a FailedFile conflict.
§Errors
Returns ApplyDiffError before applying file operations when root is not
an accessible directory, the patch envelope is malformed, an operation path
is unsafe, or the envelope contains no operations. File-specific errors are
returned in ApplyDiffReport::failed instead.
§Example
use std::path::Path;
use agents_tools::apply_diff;
let report = apply_diff(
root,
"*** Begin Patch\n*** Update File: settings.txt\n-old\n+new\n*** End Patch",
)?;
for change in &report.applied {
println!("{:?}: {}", change.kind, change.path.display());
}
for failure in &report.failed {
eprintln!("{}: {}", failure.path.display(), failure.message);
}