1+ use super :: { process_changes, Change , Offset , UnblamedHunk } ;
2+ use crate :: { BlameEntry , Outcome } ;
13use gix_diff:: blob:: intern:: TokenSource ;
24use gix_hash:: ObjectId ;
35use gix_object:: { bstr:: BStr , FindExt } ;
4- use std:: { ops:: Range , path:: PathBuf } ;
5-
6- use super :: { process_changes, Change , Offset , UnblamedHunk } ;
7- use crate :: { BlameEntry , Outcome } ;
6+ use std:: ops:: Range ;
87
98// TODO: do not instantiate anything, get everything passed as argument.
109/// Produce a list of consecutive [`BlameEntry`] instances to indicate in which commits the ranges of the file
@@ -57,22 +56,16 @@ pub fn file<E>(
5756 odb : impl gix_object:: Find + gix_object:: FindHeader ,
5857 traverse : impl IntoIterator < Item = Result < gix_traverse:: commit:: Info , E > > ,
5958 resource_cache : & mut gix_diff:: blob:: Platform ,
60- // TODO: remove
61- worktree_root : PathBuf ,
6259 file_path : & BStr ,
6360) -> Result < Outcome , E > {
64- // TODO: `worktree_root` should be removed - read everything from Commit.
65- // Worktree changes should be placed into a temporary commit.
66- // TODO: remove this and deduplicate the respective code.
67- use gix_object:: bstr:: ByteSlice ;
68- let absolute_path = worktree_root. join ( gix_path:: from_bstr ( file_path) ) ;
69-
7061 let mut traverse = traverse. into_iter ( ) . peekable ( ) ;
7162 let Some ( Ok ( suspect) ) = traverse. peek ( ) . map ( |res| res. as_ref ( ) . map ( |item| item. id ) ) else {
7263 todo ! ( "return actual error" ) ;
7364 } ;
7465
75- let original_file_blob = std:: fs:: read ( absolute_path) . unwrap ( ) ;
66+ let ( mut buf, mut buf2) = ( Vec :: new ( ) , Vec :: new ( ) ) ;
67+ let original_file_entry = find_path_entry_in_commit ( & odb, & suspect, file_path, & mut buf, & mut buf2) . unwrap ( ) ;
68+ let original_file_blob = odb. find_blob ( & original_file_entry. oid , & mut buf) . unwrap ( ) . data . to_vec ( ) ;
7669 let num_lines_in_original = {
7770 let mut interner = gix_diff:: blob:: intern:: Interner :: new ( original_file_blob. len ( ) / 100 ) ;
7871 tokens_for_diffing ( & original_file_blob)
@@ -88,12 +81,11 @@ pub fn file<E>(
8881 ) ] ;
8982
9083 let mut out = Vec :: new ( ) ;
91- let mut buf = Vec :: with_capacity ( 512 ) ;
9284 ' outer: for item in traverse {
9385 let item = item?;
9486 let suspect = item. id ;
9587
96- let parent_ids = item. parent_ids ;
88+ let mut parent_ids = item. parent_ids ;
9789 if parent_ids. is_empty ( ) {
9890 // I’m not entirely sure if this is correct yet. `suspect`, at this point, is the `id` of
9991 // the last `item` that was yielded by `traverse`, so it makes sense to assign the
@@ -110,29 +102,13 @@ pub fn file<E>(
110102 break ;
111103 }
112104
113- let commit_id = odb. find_commit ( & suspect, & mut buf) . unwrap ( ) . tree ( ) ;
114- let tree_iter = odb. find_tree_iter ( & commit_id, & mut buf) . unwrap ( ) ;
115-
116- let mut entry_buffer = Vec :: new ( ) ;
117- let Some ( entry) = tree_iter
118- . lookup_entry_by_path ( & odb, & mut entry_buffer, file_path. to_str ( ) . unwrap ( ) )
119- . unwrap ( )
120- else {
105+ let Some ( entry) = find_path_entry_in_commit ( & odb, & suspect, file_path, & mut buf, & mut buf2) else {
121106 continue ;
122107 } ;
123108
124109 if parent_ids. len ( ) == 1 {
125- let parent_id: ObjectId = * parent_ids. last ( ) . unwrap ( ) ;
126-
127- let mut buffer = Vec :: new ( ) ;
128- let parent_commit_id = odb. find_commit ( & parent_id, & mut buffer) . unwrap ( ) . tree ( ) ;
129- let parent_tree_iter = odb. find_tree_iter ( & parent_commit_id, & mut buffer) . unwrap ( ) ;
130-
131- let mut entry_buffer = Vec :: new ( ) ;
132- if let Some ( parent_entry) = parent_tree_iter
133- . lookup_entry_by_path ( & odb, & mut entry_buffer, file_path. to_str ( ) . unwrap ( ) )
134- . unwrap ( )
135- {
110+ let parent_id = parent_ids. pop ( ) . expect ( "just validated there is exactly one" ) ;
111+ if let Some ( parent_entry) = find_path_entry_in_commit ( & odb, & parent_id, file_path, & mut buf, & mut buf2) {
136112 if entry. oid == parent_entry. oid {
137113 // The blobs storing the blamed file in `entry` and `parent_entry` are identical
138114 // which is why we can pass blame to the parent without further checks.
@@ -175,25 +151,8 @@ pub fn file<E>(
175151 }
176152 }
177153 } else {
178- let mut buffer = Vec :: new ( ) ;
179- let commit_id = odb. find_commit ( & suspect, & mut buffer) . unwrap ( ) . tree ( ) ;
180- let tree_iter = odb. find_tree_iter ( & commit_id, & mut buffer) . unwrap ( ) ;
181-
182- let mut entry_buffer = Vec :: new ( ) ;
183- let entry = tree_iter
184- . lookup_entry_by_path ( & odb, & mut entry_buffer, file_path. to_str ( ) . unwrap ( ) )
185- . unwrap ( )
186- . unwrap ( ) ;
187-
188154 for parent_id in & parent_ids {
189- let mut buffer = Vec :: new ( ) ;
190- let parent_commit_id = odb. find_commit ( parent_id, & mut buffer) . unwrap ( ) . tree ( ) ;
191- let parent_tree_iter = odb. find_tree_iter ( & parent_commit_id, & mut buffer) . unwrap ( ) ;
192-
193- let mut entry_buffer = Vec :: new ( ) ;
194- if let Some ( parent_entry) = parent_tree_iter
195- . lookup_entry_by_path ( & odb, & mut entry_buffer, file_path. to_str ( ) . unwrap ( ) )
196- . unwrap ( )
155+ if let Some ( parent_entry) = find_path_entry_in_commit ( & odb, & parent_id, file_path, & mut buf, & mut buf2)
197156 {
198157 if entry. oid == parent_entry. oid {
199158 // The blobs storing the blamed file in `entry` and `parent_entry` are
@@ -435,6 +394,21 @@ fn blob_changes(
435394 gix_diff:: blob:: diff ( gix_diff:: blob:: Algorithm :: Histogram , & input, change_recorder)
436395}
437396
397+ fn find_path_entry_in_commit (
398+ odb : & impl gix_object:: Find ,
399+ commit : & gix_hash:: oid ,
400+ file_path : & BStr ,
401+ buf : & mut Vec < u8 > ,
402+ buf2 : & mut Vec < u8 > ,
403+ ) -> Option < gix_object:: tree:: Entry > {
404+ let commit_id = odb. find_commit ( commit, buf) . unwrap ( ) . tree ( ) ;
405+ let tree_iter = odb. find_tree_iter ( & commit_id, buf) . unwrap ( ) ;
406+
407+ tree_iter
408+ . lookup_entry ( odb, buf2, file_path. split ( |b| * b == b'/' ) )
409+ . unwrap ( )
410+ }
411+
438412/// Return an iterator over tokens for use in diffing. These usually lines, but iit's important to unify them
439413/// so the later access shows the right thing.
440414pub ( crate ) fn tokens_for_diffing ( data : & [ u8 ] ) -> impl TokenSource < Token = & [ u8 ] > {
0 commit comments