@@ -8,6 +8,9 @@ use std::ptr;
8
8
use std:: str;
9
9
10
10
use crate :: build:: { CheckoutBuilder , RepoBuilder } ;
11
+ use crate :: diff:: {
12
+ binary_cb_c, file_cb_c, hunk_cb_c, line_cb_c, BinaryCb , DiffCallbacks , FileCb , HunkCb , LineCb ,
13
+ } ;
11
14
use crate :: oid_array:: OidArray ;
12
15
use crate :: stash:: { stash_cb, StashApplyOptions , StashCbData } ;
13
16
use crate :: string_array:: StringArray ;
@@ -2249,6 +2252,78 @@ impl Repository {
2249
2252
}
2250
2253
}
2251
2254
2255
+ /// Directly run a diff on two blobs.
2256
+ ///
2257
+ /// Compared to a file, a blob lacks some contextual information. As such, the
2258
+ /// `DiffFile` given to the callback will have some fake data; i.e. mode will be
2259
+ /// 0 and path will be `None`.
2260
+ ///
2261
+ /// `None` is allowed for either `old_blob` or `new_blob` and will be treated
2262
+ /// as an empty blob, with the oid set to zero in the `DiffFile`. Passing `None`
2263
+ /// for both blobs is a noop; no callbacks will be made at all.
2264
+ ///
2265
+ /// We do run a binary content check on the blob content and if either blob looks
2266
+ /// like binary data, the `DiffFile` binary attribute will be set to 1 and no call to
2267
+ /// the `hunk_cb` nor `line_cb` will be made (unless you set the `force_text`
2268
+ /// option).
2269
+ pub fn diff_blobs (
2270
+ & self ,
2271
+ old_blob : Option < & Blob < ' _ > > ,
2272
+ old_as_path : Option < & str > ,
2273
+ new_blob : Option < & Blob < ' _ > > ,
2274
+ new_as_path : Option < & str > ,
2275
+ opts : Option < & mut DiffOptions > ,
2276
+ file_cb : Option < & mut FileCb < ' _ > > ,
2277
+ binary_cb : Option < & mut BinaryCb < ' _ > > ,
2278
+ hunk_cb : Option < & mut HunkCb < ' _ > > ,
2279
+ line_cb : Option < & mut LineCb < ' _ > > ,
2280
+ ) -> Result < ( ) , Error > {
2281
+ let old_as_path = crate :: opt_cstr ( old_as_path) ?;
2282
+ let new_as_path = crate :: opt_cstr ( new_as_path) ?;
2283
+ let mut cbs = DiffCallbacks {
2284
+ file : file_cb,
2285
+ binary : binary_cb,
2286
+ hunk : hunk_cb,
2287
+ line : line_cb,
2288
+ } ;
2289
+ let ptr = & mut cbs as * mut _ ;
2290
+ unsafe {
2291
+ let file_cb_c: raw:: git_diff_file_cb = if cbs. file . is_some ( ) {
2292
+ Some ( file_cb_c)
2293
+ } else {
2294
+ None
2295
+ } ;
2296
+ let binary_cb_c: raw:: git_diff_binary_cb = if cbs. binary . is_some ( ) {
2297
+ Some ( binary_cb_c)
2298
+ } else {
2299
+ None
2300
+ } ;
2301
+ let hunk_cb_c: raw:: git_diff_hunk_cb = if cbs. hunk . is_some ( ) {
2302
+ Some ( hunk_cb_c)
2303
+ } else {
2304
+ None
2305
+ } ;
2306
+ let line_cb_c: raw:: git_diff_line_cb = if cbs. line . is_some ( ) {
2307
+ Some ( line_cb_c)
2308
+ } else {
2309
+ None
2310
+ } ;
2311
+ try_call ! ( raw:: git_diff_blobs(
2312
+ old_blob. map( |s| s. raw( ) ) ,
2313
+ old_as_path,
2314
+ new_blob. map( |s| s. raw( ) ) ,
2315
+ new_as_path,
2316
+ opts. map( |s| s. raw( ) ) ,
2317
+ file_cb_c,
2318
+ binary_cb_c,
2319
+ hunk_cb_c,
2320
+ line_cb_c,
2321
+ ptr as * mut _
2322
+ ) ) ;
2323
+ Ok ( ( ) )
2324
+ }
2325
+ }
2326
+
2252
2327
/// Create a diff with the difference between two tree objects.
2253
2328
///
2254
2329
/// This is equivalent to `git diff <old-tree> <new-tree>`
0 commit comments