Skip to main content

ParseOptions

Struct ParseOptions 

Source
pub struct ParseOptions { /* private fields */ }
Expand description

Options for parsing patch content.

Use ParseOptions::unidiff() or ParseOptions::gitdiff() to create options for the desired format.

§Binary Files

When parsing git diffs, binary file changes are detected by:

  • Binary files a/path and b/path differ (git diff without --binary flag)
  • GIT binary patch (from git diff --binary)

Note that this is not a documented Git behavior, so the implementation here is subject to change if Git changes.

§Example

use diffy::patch_set::ParseOptions;
use diffy::patch_set::PatchSet;

let s = "\
--- original
+++ modified
@@ -1 +1 @@
-old
+new
";

let patches: Vec<_> = PatchSet::parse(s, ParseOptions::unidiff())
    .collect::<Result<_, _>>()
    .unwrap();
assert_eq!(patches.len(), 1);

Implementations§

Source§

impl ParseOptions

Source

pub fn unidiff() -> Self

Parse as standard unified diff format.

Supported:

  • ---/+++ file headers
  • @@ ... @@ hunks
  • modify and rename files
  • create files (--- /dev/null)
  • delete files (+++ /dev/null)
  • Skip preamble, headers, and email signature trailer
Source

pub fn gitdiff() -> Self

Parse as git extended diff format.

Supports all features of unidiff() plus:

  • diff --git headers
  • Extended headers (new file mode, deleted file mode, etc.)
  • Rename/copy detection (rename from/rename to, copy from/copy to)
  • Binary file detection
Examples found in repository?
examples/apply.rs (line 45)
42fn apply_patch_file(patch_file: &Path, dst: &Path) -> Result<(), Box<dyn std::error::Error>> {
43    let content = fs::read(patch_file)?;
44
45    let patches = PatchSet::parse_bytes(&content, ParseOptions::gitdiff());
46
47    for file_patch in patches {
48        let file_patch = file_patch?;
49        let operation = {
50            let op = file_patch.operation();
51            // Rename/Copy paths come from git headers without a/b prefix.
52            let strip = match op {
53                FileOperation::Rename { .. } | FileOperation::Copy { .. } => 0,
54                _ => 1,
55            };
56            op.strip_prefix(strip)
57        };
58
59        match operation {
60            FileOperation::Create(path) => {
61                let target = dst.join(path_from_bytes(&path)?);
62                let patched = match file_patch.patch() {
63                    PatchKind::Text(patch) => apply_bytes(&[], patch)?,
64                    PatchKind::Binary(BinaryPatch::Marker) => continue,
65                    PatchKind::Binary(patch) => patch.apply(&[])?,
66                };
67                create_parent_dirs(&target)?;
68                fs::write(&target, patched)?;
69                eprintln!("create {}", target.display());
70            }
71            FileOperation::Delete(path) => {
72                let target = dst.join(path_from_bytes(&path)?);
73                fs::remove_file(&target)?;
74                eprintln!("delete {}", target.display());
75            }
76            FileOperation::Modify { original, modified } => {
77                let src_path = dst.join(path_from_bytes(&original)?);
78                let dst_path = dst.join(path_from_bytes(&modified)?);
79                let patched = match file_patch.patch() {
80                    PatchKind::Text(patch) => {
81                        let base = fs::read(&src_path)?;
82                        apply_bytes(&base, patch)?
83                    }
84                    PatchKind::Binary(BinaryPatch::Marker) => continue,
85                    PatchKind::Binary(patch) => {
86                        let base = fs::read(&src_path)?;
87                        patch.apply(&base)?
88                    }
89                };
90                create_parent_dirs(&dst_path)?;
91                fs::write(&dst_path, patched)?;
92                if src_path != dst_path {
93                    fs::remove_file(&src_path)?;
94                    eprintln!("rename {} -> {}", src_path.display(), dst_path.display());
95                } else {
96                    eprintln!("modify {}", dst_path.display());
97                }
98            }
99            FileOperation::Rename { from, to } => {
100                let src_path = dst.join(path_from_bytes(&from)?);
101                let dst_path = dst.join(path_from_bytes(&to)?);
102                create_parent_dirs(&dst_path)?;
103                fs::rename(&src_path, &dst_path)?;
104                eprintln!("rename {} -> {}", src_path.display(), dst_path.display());
105            }
106            FileOperation::Copy { from, to } => {
107                let src_path = dst.join(path_from_bytes(&from)?);
108                let dst_path = dst.join(path_from_bytes(&to)?);
109                create_parent_dirs(&dst_path)?;
110                fs::copy(&src_path, &dst_path)?;
111                eprintln!("copy {} -> {}", src_path.display(), dst_path.display());
112            }
113        }
114    }
115
116    Ok(())
117}

Trait Implementations§

Source§

impl Clone for ParseOptions

Source§

fn clone(&self) -> ParseOptions

Returns a duplicate of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for ParseOptions

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.