3 use libc
::{c_char, c_int, c_void}
;
5 use {raw, Blob, Buf, Diff, DiffDelta, DiffHunk, DiffLine, DiffOptions, Error}
;
6 use diff
::{LineCb, print_cb}
;
7 use util
::{Binding, into_opt_c_string}
;
9 /// A structure representing the text changes in a single diff delta.
11 /// This is an opaque structure.
13 raw
: *mut raw
::git_patch
,
16 unsafe impl Send
for Patch {}
18 impl Binding
for Patch
{
19 type Raw
= *mut raw
::git_patch
;
20 unsafe fn from_raw(raw
: Self::Raw
) -> Patch
{
23 fn raw(&self) -> Self::Raw { self.raw }
28 unsafe { raw::git_patch_free(self.raw) }
33 /// Return a Patch for one file in a Diff.
35 /// Returns Ok(None) for an unchanged or binary file.
36 pub fn from_diff(diff
: &Diff
, idx
: usize) -> Result
<Option
<Patch
>, Error
> {
37 let mut ret
= ptr
::null_mut();
39 try_call
!(raw
::git_patch_from_diff(&mut ret
, diff
.raw(), idx
));
40 Ok(Binding
::from_raw_opt(ret
))
44 /// Generate a Patch by diffing two blobs.
45 pub fn from_blobs(old_blob
: &Blob
,
46 old_path
: Option
<&Path
>,
48 new_path
: Option
<&Path
>,
49 opts
: Option
<&mut DiffOptions
>)
50 -> Result
<Patch
, Error
>
52 let mut ret
= ptr
::null_mut();
53 let old_path
= try
!(into_opt_c_string(old_path
));
54 let new_path
= try
!(into_opt_c_string(new_path
));
56 try_call
!(raw
::git_patch_from_blobs(&mut ret
,
61 opts
.map(|s
| s
.raw())));
62 Ok(Binding
::from_raw(ret
))
66 /// Generate a Patch by diffing a blob and a buffer.
67 pub fn from_blob_and_buffer(old_blob
: &Blob
,
68 old_path
: Option
<&Path
>,
70 new_path
: Option
<&Path
>,
71 opts
: Option
<&mut DiffOptions
>)
72 -> Result
<Patch
, Error
>
74 let mut ret
= ptr
::null_mut();
75 let old_path
= try
!(into_opt_c_string(old_path
));
76 let new_path
= try
!(into_opt_c_string(new_path
));
78 try_call
!(raw
::git_patch_from_blob_and_buffer(&mut ret
,
81 new_buffer
.as_ptr() as *const c_char
,
84 opts
.map(|s
| s
.raw())));
85 Ok(Binding
::from_raw(ret
))
89 /// Generate a Patch by diffing two buffers.
90 pub fn from_buffers(old_buffer
: &[u8],
91 old_path
: Option
<&Path
>,
93 new_path
: Option
<&Path
>,
94 opts
: Option
<&mut DiffOptions
>)
95 -> Result
<Patch
, Error
>
97 let mut ret
= ptr
::null_mut();
98 let old_path
= try
!(into_opt_c_string(old_path
));
99 let new_path
= try
!(into_opt_c_string(new_path
));
101 try_call
!(raw
::git_patch_from_buffers(&mut ret
,
102 old_buffer
.as_ptr() as *const c_void
,
105 new_buffer
.as_ptr() as *const c_char
,
108 opts
.map(|s
| s
.raw())));
109 Ok(Binding
::from_raw(ret
))
113 /// Get the DiffDelta associated with the Patch.
114 pub fn delta(&self) -> DiffDelta
{
116 Binding
::from_raw(raw
::git_patch_get_delta(self.raw
) as *mut _
)
120 /// Get the number of hunks in the Patch.
121 pub fn num_hunks(&self) -> usize {
123 raw
::git_patch_num_hunks(self.raw
)
127 /// Get the number of lines of context, additions, and deletions in the Patch.
128 pub fn line_stats(&self) -> Result
<(usize, usize, usize), Error
> {
130 let mut additions
= 0;
131 let mut deletions
= 0;
133 try_call
!(raw
::git_patch_line_stats(&mut context
,
138 Ok((context
, additions
, deletions
))
141 /// Get a DiffHunk and its total line count from the Patch.
142 pub fn hunk(&mut self, hunk_idx
: usize) -> Result
<(DiffHunk
, usize), Error
> {
143 let mut ret
= ptr
::null();
146 try_call
!(raw
::git_patch_get_hunk(&mut ret
, &mut lines
, self.raw
, hunk_idx
));
147 Ok((Binding
::from_raw(ret
), lines
))
151 /// Get the number of lines in a hunk.
152 pub fn num_lines_in_hunk(&self, hunk_idx
: usize) -> Result
<usize, Error
> {
154 Ok(try_call
!(raw
::git_patch_num_lines_in_hunk(self.raw
, hunk_idx
)) as usize)
158 /// Get a DiffLine from a hunk of the Patch.
159 pub fn line_in_hunk(&mut self,
161 line_of_hunk
: usize) -> Result
<DiffLine
, Error
> {
162 let mut ret
= ptr
::null();
164 try_call
!(raw
::git_patch_get_line_in_hunk(&mut ret
,
168 Ok(Binding
::from_raw(ret
))
172 /// Get the size of a Patch's diff data in bytes.
174 include_context
: bool
,
175 include_hunk_headers
: bool
,
176 include_file_headers
: bool
) -> usize {
178 raw
::git_patch_size(self.raw
,
179 include_context
as c_int
,
180 include_hunk_headers
as c_int
,
181 include_file_headers
as c_int
)
185 /// Print the Patch to text via a callback.
186 pub fn print(&mut self, mut line_cb
: &mut LineCb
) -> Result
<(), Error
> {
187 let ptr
= &mut line_cb
as *mut _
as *mut c_void
;
189 try_call
!(raw
::git_patch_print(self.raw
, print_cb
, ptr
));
194 /// Get the Patch text as a Buf.
195 pub fn to_buf(&mut self) -> Result
<Buf
, Error
> {
196 let buf
= Buf
::new();
198 try_call
!(raw
::git_patch_to_buf(buf
.raw(), self.raw
));