]> git.proxmox.com Git - rustc.git/blob - src/vendor/git2/src/patch.rs
New upstream version 1.19.0+dfsg1
[rustc.git] / src / vendor / git2 / src / patch.rs
1 use std::path::Path;
2 use std::ptr;
3 use libc::{c_char, c_int, c_void};
4
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};
8
9 /// A structure representing the text changes in a single diff delta.
10 ///
11 /// This is an opaque structure.
12 pub struct Patch {
13 raw: *mut raw::git_patch,
14 }
15
16 unsafe impl Send for Patch {}
17
18 impl Binding for Patch {
19 type Raw = *mut raw::git_patch;
20 unsafe fn from_raw(raw: Self::Raw) -> Patch {
21 Patch { raw: raw }
22 }
23 fn raw(&self) -> Self::Raw { self.raw }
24 }
25
26 impl Drop for Patch {
27 fn drop(&mut self) {
28 unsafe { raw::git_patch_free(self.raw) }
29 }
30 }
31
32 impl Patch {
33 /// Return a Patch for one file in a Diff.
34 ///
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();
38 unsafe {
39 try_call!(raw::git_patch_from_diff(&mut ret, diff.raw(), idx));
40 Ok(Binding::from_raw_opt(ret))
41 }
42 }
43
44 /// Generate a Patch by diffing two blobs.
45 pub fn from_blobs(old_blob: &Blob,
46 old_path: Option<&Path>,
47 new_blob: &Blob,
48 new_path: Option<&Path>,
49 opts: Option<&mut DiffOptions>)
50 -> Result<Patch, Error>
51 {
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));
55 unsafe {
56 try_call!(raw::git_patch_from_blobs(&mut ret,
57 old_blob.raw(),
58 old_path,
59 new_blob.raw(),
60 new_path,
61 opts.map(|s| s.raw())));
62 Ok(Binding::from_raw(ret))
63 }
64 }
65
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>,
69 new_buffer: &[u8],
70 new_path: Option<&Path>,
71 opts: Option<&mut DiffOptions>)
72 -> Result<Patch, Error>
73 {
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));
77 unsafe {
78 try_call!(raw::git_patch_from_blob_and_buffer(&mut ret,
79 old_blob.raw(),
80 old_path,
81 new_buffer.as_ptr() as *const c_char,
82 new_buffer.len(),
83 new_path,
84 opts.map(|s| s.raw())));
85 Ok(Binding::from_raw(ret))
86 }
87 }
88
89 /// Generate a Patch by diffing two buffers.
90 pub fn from_buffers(old_buffer: &[u8],
91 old_path: Option<&Path>,
92 new_buffer: &[u8],
93 new_path: Option<&Path>,
94 opts: Option<&mut DiffOptions>)
95 -> Result<Patch, Error>
96 {
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));
100 unsafe {
101 try_call!(raw::git_patch_from_buffers(&mut ret,
102 old_buffer.as_ptr() as *const c_void,
103 old_buffer.len(),
104 old_path,
105 new_buffer.as_ptr() as *const c_char,
106 new_buffer.len(),
107 new_path,
108 opts.map(|s| s.raw())));
109 Ok(Binding::from_raw(ret))
110 }
111 }
112
113 /// Get the DiffDelta associated with the Patch.
114 pub fn delta(&self) -> DiffDelta {
115 unsafe {
116 Binding::from_raw(raw::git_patch_get_delta(self.raw) as *mut _)
117 }
118 }
119
120 /// Get the number of hunks in the Patch.
121 pub fn num_hunks(&self) -> usize {
122 unsafe {
123 raw::git_patch_num_hunks(self.raw)
124 }
125 }
126
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> {
129 let mut context = 0;
130 let mut additions = 0;
131 let mut deletions = 0;
132 unsafe {
133 try_call!(raw::git_patch_line_stats(&mut context,
134 &mut additions,
135 &mut deletions,
136 self.raw));
137 }
138 Ok((context, additions, deletions))
139 }
140
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();
144 let mut lines = 0;
145 unsafe {
146 try_call!(raw::git_patch_get_hunk(&mut ret, &mut lines, self.raw, hunk_idx));
147 Ok((Binding::from_raw(ret), lines))
148 }
149 }
150
151 /// Get the number of lines in a hunk.
152 pub fn num_lines_in_hunk(&self, hunk_idx: usize) -> Result<usize, Error> {
153 unsafe {
154 Ok(try_call!(raw::git_patch_num_lines_in_hunk(self.raw, hunk_idx)) as usize)
155 }
156 }
157
158 /// Get a DiffLine from a hunk of the Patch.
159 pub fn line_in_hunk(&mut self,
160 hunk_idx: usize,
161 line_of_hunk: usize) -> Result<DiffLine, Error> {
162 let mut ret = ptr::null();
163 unsafe {
164 try_call!(raw::git_patch_get_line_in_hunk(&mut ret,
165 self.raw,
166 hunk_idx,
167 line_of_hunk));
168 Ok(Binding::from_raw(ret))
169 }
170 }
171
172 /// Get the size of a Patch's diff data in bytes.
173 pub fn size(&self,
174 include_context: bool,
175 include_hunk_headers: bool,
176 include_file_headers: bool) -> usize {
177 unsafe {
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)
182 }
183 }
184
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;
188 unsafe {
189 try_call!(raw::git_patch_print(self.raw, print_cb, ptr));
190 Ok(())
191 }
192 }
193
194 /// Get the Patch text as a Buf.
195 pub fn to_buf(&mut self) -> Result<Buf, Error> {
196 let buf = Buf::new();
197 unsafe {
198 try_call!(raw::git_patch_to_buf(buf.raw(), self.raw));
199 }
200 Ok(buf)
201 }
202 }