1
1
use super :: { process_changes, Change , Offset , UnblamedHunk } ;
2
- use crate :: { BlameEntry , Outcome , Statistics } ;
2
+ use crate :: { BlameEntry , Error , Outcome , Statistics } ;
3
3
use gix_diff:: blob:: intern:: TokenSource ;
4
4
use gix_hash:: ObjectId ;
5
5
use gix_object:: { bstr:: BStr , FindExt } ;
@@ -57,18 +57,24 @@ pub fn file<E>(
57
57
traverse : impl IntoIterator < Item = Result < gix_traverse:: commit:: Info , E > > ,
58
58
resource_cache : & mut gix_diff:: blob:: Platform ,
59
59
file_path : & BStr ,
60
- ) -> Result < Outcome , E > {
60
+ ) -> Result < Outcome , Error >
61
+ where
62
+ E : Into < Box < dyn std:: error:: Error + Send + Sync + ' static > > ,
63
+ {
61
64
let mut traverse = traverse. into_iter ( ) . peekable ( ) ;
62
65
let Some ( Ok ( suspect) ) = traverse. peek ( ) . map ( |res| res. as_ref ( ) . map ( |item| item. id ) ) else {
63
- todo ! ( " return actual error" ) ;
66
+ return Err ( Error :: EmptyTraversal ) ;
64
67
} ;
65
68
let _span = gix_trace:: coarse!( "gix_blame::file()" , ?file_path, ?suspect) ;
66
69
67
70
let mut stats = Statistics :: default ( ) ;
68
71
let ( mut buf, mut buf2, mut buf3) = ( Vec :: new ( ) , Vec :: new ( ) , Vec :: new ( ) ) ;
69
- let original_file_entry =
70
- find_path_entry_in_commit ( & odb, & suspect, file_path, & mut buf, & mut buf2, & mut stats) . unwrap ( ) ;
71
- let original_file_blob = odb. find_blob ( & original_file_entry. oid , & mut buf) . unwrap ( ) . data . to_vec ( ) ;
72
+ let original_file_entry = find_path_entry_in_commit ( & odb, & suspect, file_path, & mut buf, & mut buf2, & mut stats) ?
73
+ . ok_or_else ( || Error :: FileMissing {
74
+ file_path : file_path. to_owned ( ) ,
75
+ commit_id : suspect,
76
+ } ) ?;
77
+ let original_file_blob = odb. find_blob ( & original_file_entry. oid , & mut buf) ?. data . to_vec ( ) ;
72
78
let num_lines_in_original = {
73
79
let mut interner = gix_diff:: blob:: intern:: Interner :: new ( original_file_blob. len ( ) / 100 ) ;
74
80
tokens_for_diffing ( & original_file_blob)
@@ -78,15 +84,15 @@ pub fn file<E>(
78
84
} ;
79
85
80
86
let mut hunks_to_blame = vec ! [ UnblamedHunk :: new(
81
- 0 ..num_lines_in_original. try_into ( ) . unwrap ( ) ,
87
+ 0 ..num_lines_in_original as u32 ,
82
88
suspect,
83
89
Offset :: Added ( 0 ) ,
84
90
) ] ;
85
91
86
92
let mut out = Vec :: new ( ) ;
87
93
let mut diff_state = gix_diff:: tree:: State :: default ( ) ;
88
94
' outer: for item in traverse {
89
- let item = item?;
95
+ let item = item. map_err ( |err| Error :: Traverse ( err . into ( ) ) ) ?;
90
96
let suspect = item. id ;
91
97
stats. commits_traversed += 1 ;
92
98
@@ -107,14 +113,14 @@ pub fn file<E>(
107
113
break ;
108
114
}
109
115
110
- let Some ( entry) = find_path_entry_in_commit ( & odb, & suspect, file_path, & mut buf, & mut buf2, & mut stats) else {
116
+ let Some ( entry) = find_path_entry_in_commit ( & odb, & suspect, file_path, & mut buf, & mut buf2, & mut stats) ? else {
111
117
continue ;
112
118
} ;
113
119
114
120
if parent_ids. len ( ) == 1 {
115
121
let parent_id = parent_ids. pop ( ) . expect ( "just validated there is exactly one" ) ;
116
122
if let Some ( parent_entry) =
117
- find_path_entry_in_commit ( & odb, & parent_id, file_path, & mut buf, & mut buf2, & mut stats)
123
+ find_path_entry_in_commit ( & odb, & parent_id, file_path, & mut buf, & mut buf2, & mut stats) ?
118
124
{
119
125
if entry. oid == parent_entry. oid {
120
126
// The blobs storing the blamed file in `entry` and `parent_entry` are identical
@@ -126,7 +132,7 @@ pub fn file<E>(
126
132
}
127
133
}
128
134
129
- let Some ( modification ) = tree_diff_at_file_path (
135
+ let changes_for_file_path = tree_diff_at_file_path (
130
136
& odb,
131
137
file_path,
132
138
item. id ,
@@ -136,7 +142,8 @@ pub fn file<E>(
136
142
& mut buf,
137
143
& mut buf2,
138
144
& mut buf3,
139
- ) else {
145
+ ) ?;
146
+ let Some ( modification) = changes_for_file_path else {
140
147
// None of the changes affected the file we’re currently blaming. Pass blame to parent.
141
148
for unblamed_hunk in & mut hunks_to_blame {
142
149
unblamed_hunk. pass_blame ( suspect, parent_id) ;
@@ -159,7 +166,7 @@ pub fn file<E>(
159
166
}
160
167
gix_diff:: tree:: recorder:: Change :: Deletion { .. } => todo ! ( ) ,
161
168
gix_diff:: tree:: recorder:: Change :: Modification { previous_oid, oid, .. } => {
162
- let changes = blob_changes ( & odb, resource_cache, oid, previous_oid, file_path, & mut stats) ;
169
+ let changes = blob_changes ( & odb, resource_cache, oid, previous_oid, file_path, & mut stats) ? ;
163
170
hunks_to_blame = process_changes ( & mut out, hunks_to_blame, changes, suspect) ;
164
171
for unblamed_hunk in & mut hunks_to_blame {
165
172
unblamed_hunk. pass_blame ( suspect, parent_id) ;
@@ -169,7 +176,7 @@ pub fn file<E>(
169
176
} else {
170
177
for parent_id in & parent_ids {
171
178
if let Some ( parent_entry) =
172
- find_path_entry_in_commit ( & odb, parent_id, file_path, & mut buf, & mut buf2, & mut stats)
179
+ find_path_entry_in_commit ( & odb, parent_id, file_path, & mut buf, & mut buf2, & mut stats) ?
173
180
{
174
181
if entry. oid == parent_entry. oid {
175
182
// The blobs storing the blamed file in `entry` and `parent_entry` are
@@ -194,7 +201,7 @@ pub fn file<E>(
194
201
& mut buf,
195
202
& mut buf2,
196
203
& mut buf3,
197
- ) ;
204
+ ) ? ;
198
205
let Some ( modification) = changes_for_file_path else {
199
206
// None of the changes affected the file we’re currently blaming. Pass blame
200
207
// to parent.
@@ -215,7 +222,7 @@ pub fn file<E>(
215
222
}
216
223
gix_diff:: tree:: recorder:: Change :: Deletion { .. } => todo ! ( ) ,
217
224
gix_diff:: tree:: recorder:: Change :: Modification { previous_oid, oid, .. } => {
218
- let changes = blob_changes ( & odb, resource_cache, oid, previous_oid, file_path, & mut stats) ;
225
+ let changes = blob_changes ( & odb, resource_cache, oid, previous_oid, file_path, & mut stats) ? ;
219
226
hunks_to_blame = process_changes ( & mut out, hunks_to_blame, changes, suspect) ;
220
227
for unblamed_hunk in & mut hunks_to_blame {
221
228
unblamed_hunk. pass_blame ( suspect, parent_id) ;
@@ -300,32 +307,28 @@ fn tree_diff_at_file_path(
300
307
commit_buf : & mut Vec < u8 > ,
301
308
lhs_tree_buf : & mut Vec < u8 > ,
302
309
rhs_tree_buf : & mut Vec < u8 > ,
303
- ) -> Option < gix_diff:: tree:: recorder:: Change > {
304
- let parent_tree = odb. find_commit ( & parent_id, commit_buf) . unwrap ( ) . tree ( ) ;
310
+ ) -> Result < Option < gix_diff:: tree:: recorder:: Change > , Error > {
311
+ let parent_tree = odb. find_commit ( & parent_id, commit_buf) ? . tree ( ) ;
305
312
stats. commits_to_tree += 1 ;
306
313
307
- let parent_tree_iter = odb
308
- . find ( & parent_tree, lhs_tree_buf)
309
- . unwrap ( )
310
- . try_into_tree_iter ( )
311
- . unwrap ( ) ;
314
+ let parent_tree_iter = odb. find_tree_iter ( & parent_tree, lhs_tree_buf) ?;
312
315
stats. trees_decoded += 1 ;
313
316
314
- let tree_id = odb. find_commit ( & id, commit_buf) . unwrap ( ) . tree ( ) ;
317
+ let tree_id = odb. find_commit ( & id, commit_buf) ? . tree ( ) ;
315
318
stats. commits_to_tree += 1 ;
316
319
317
- let tree_iter = odb. find ( & tree_id, rhs_tree_buf) . unwrap ( ) . try_into_tree_iter ( ) . unwrap ( ) ;
320
+ let tree_iter = odb. find_tree_iter ( & tree_id, rhs_tree_buf) ? ;
318
321
stats. trees_decoded += 1 ;
319
322
320
323
let mut recorder = gix_diff:: tree:: Recorder :: default ( ) ;
321
- gix_diff:: tree ( parent_tree_iter, tree_iter, state, & odb, & mut recorder) . unwrap ( ) ;
324
+ gix_diff:: tree ( parent_tree_iter, tree_iter, state, & odb, & mut recorder) ? ;
322
325
stats. trees_diffed += 1 ;
323
326
324
- recorder. records . into_iter ( ) . find ( |change| match change {
327
+ Ok ( recorder. records . into_iter ( ) . find ( |change| match change {
325
328
gix_diff:: tree:: recorder:: Change :: Modification { path, .. } => path == file_path,
326
329
gix_diff:: tree:: recorder:: Change :: Addition { path, .. } => path == file_path,
327
330
gix_diff:: tree:: recorder:: Change :: Deletion { path, .. } => path == file_path,
328
- } )
331
+ } ) )
329
332
}
330
333
331
334
fn blob_changes (
@@ -335,7 +338,7 @@ fn blob_changes(
335
338
previous_oid : ObjectId ,
336
339
file_path : & BStr ,
337
340
stats : & mut Statistics ,
338
- ) -> Vec < Change > {
341
+ ) -> Result < Vec < Change > , Error > {
339
342
/// Record all [`Change`]s to learn about additions, deletions and unchanged portions of a *Blamed File*.
340
343
struct ChangeRecorder {
341
344
last_seen_after_end : u32 ,
@@ -387,35 +390,32 @@ fn blob_changes(
387
390
}
388
391
}
389
392
390
- resource_cache
391
- . set_resource (
392
- previous_oid,
393
- gix_object:: tree:: EntryKind :: Blob ,
394
- file_path,
395
- gix_diff:: blob:: ResourceKind :: OldOrSource ,
396
- & odb,
397
- )
398
- . unwrap ( ) ;
399
- resource_cache
400
- . set_resource (
401
- oid,
402
- gix_object:: tree:: EntryKind :: Blob ,
403
- file_path,
404
- gix_diff:: blob:: ResourceKind :: NewOrDestination ,
405
- & odb,
406
- )
407
- . unwrap ( ) ;
408
-
409
- let outcome = resource_cache. prepare_diff ( ) . unwrap ( ) ;
393
+ resource_cache. set_resource (
394
+ previous_oid,
395
+ gix_object:: tree:: EntryKind :: Blob ,
396
+ file_path,
397
+ gix_diff:: blob:: ResourceKind :: OldOrSource ,
398
+ & odb,
399
+ ) ?;
400
+ resource_cache. set_resource (
401
+ oid,
402
+ gix_object:: tree:: EntryKind :: Blob ,
403
+ file_path,
404
+ gix_diff:: blob:: ResourceKind :: NewOrDestination ,
405
+ & odb,
406
+ ) ?;
407
+
408
+ let outcome = resource_cache. prepare_diff ( ) ?;
410
409
let input = gix_diff:: blob:: intern:: InternedInput :: new (
411
410
tokens_for_diffing ( outcome. old . data . as_slice ( ) . unwrap_or_default ( ) ) ,
412
411
tokens_for_diffing ( outcome. new . data . as_slice ( ) . unwrap_or_default ( ) ) ,
413
412
) ;
414
413
let number_of_lines_in_destination = input. after . len ( ) ;
415
- let change_recorder = ChangeRecorder :: new ( number_of_lines_in_destination. try_into ( ) . unwrap ( ) ) ;
414
+ let change_recorder = ChangeRecorder :: new ( number_of_lines_in_destination as u32 ) ;
416
415
416
+ let res = gix_diff:: blob:: diff ( gix_diff:: blob:: Algorithm :: Histogram , & input, change_recorder) ;
417
417
stats. blobs_diffed += 1 ;
418
- gix_diff :: blob :: diff ( gix_diff :: blob :: Algorithm :: Histogram , & input , change_recorder )
418
+ Ok ( res )
419
419
}
420
420
421
421
fn find_path_entry_in_commit (
@@ -425,19 +425,19 @@ fn find_path_entry_in_commit(
425
425
buf : & mut Vec < u8 > ,
426
426
buf2 : & mut Vec < u8 > ,
427
427
stats : & mut Statistics ,
428
- ) -> Option < gix_object:: tree:: Entry > {
429
- let commit_id = odb. find_commit ( commit, buf) . unwrap ( ) . tree ( ) ;
430
- let tree_iter = odb. find_tree_iter ( & commit_id, buf) . unwrap ( ) ;
428
+ ) -> Result < Option < gix_object:: tree:: Entry > , Error > {
429
+ let commit_id = odb. find_commit ( commit, buf) ?. tree ( ) ;
431
430
stats. commits_to_tree += 1 ;
431
+ let tree_iter = odb. find_tree_iter ( & commit_id, buf) ?;
432
432
stats. trees_decoded += 1 ;
433
433
434
- tree_iter
435
- . lookup_entry (
436
- odb ,
437
- buf2 ,
438
- file_path . split ( |b| * b == b'/' ) . inspect ( |_| stats . trees_decoded += 1 ) ,
439
- )
440
- . unwrap ( )
434
+ let res = tree_iter. lookup_entry (
435
+ odb ,
436
+ buf2 ,
437
+ file_path . split ( |b| * b == b'/' ) . inspect ( |_| stats . trees_decoded += 1 ) ,
438
+ ) ? ;
439
+ stats . trees_decoded -= 1 ;
440
+ Ok ( res )
441
441
}
442
442
443
443
/// Return an iterator over tokens for use in diffing. These usually lines, but iit's important to unify them
0 commit comments