@@ -6,24 +6,35 @@ use hashbrown::raw::RawTable;
66use std:: hash:: Hasher ;
77use std:: ops:: Deref ;
88
9- #[ derive( Default ) ]
109pub ( crate ) struct Delegate {
1110 changes : Vec < Change > ,
11+ resource_cache : gix:: diff:: blob:: Platform ,
1212 /// All changes that happen within a file, along the line-number it happens in .
1313 per_file_changes : Vec < ( usize , Change ) > ,
1414 err : Option < Error > ,
1515}
1616
17+ impl Delegate {
18+ pub ( crate ) fn new ( resource_cache : gix:: diff:: blob:: Platform ) -> Self {
19+ Delegate {
20+ resource_cache,
21+ changes : Default :: default ( ) ,
22+ per_file_changes : Default :: default ( ) ,
23+ err : None ,
24+ }
25+ }
26+ }
27+
1728impl Delegate {
1829 pub fn handle (
1930 & mut self ,
2031 change : gix:: object:: tree:: diff:: Change < ' _ , ' _ , ' _ > ,
2132 ) -> Result < gix:: object:: tree:: diff:: Action , Error > {
2233 use gix:: bstr:: ByteSlice ;
2334 use gix:: object:: tree:: diff:: change:: Event :: * ;
24- use gix:: objs:: tree:: EntryMode :: * ;
35+ use gix:: objs:: tree:: EntryKind :: * ;
2536 fn entry_data (
26- entry : gix:: objs:: tree:: EntryMode ,
37+ entry : gix:: objs:: tree:: EntryKind ,
2738 id : gix:: Id < ' _ > ,
2839 ) -> Result < Option < gix:: Object < ' _ > > , Error > {
2940 matches ! ( entry, Blob | BlobExecutable )
@@ -40,7 +51,7 @@ impl Delegate {
4051 unreachable ! ( "BUG: this is disabled so shouldn't happen" )
4152 }
4253 Addition { entry_mode, id } => {
43- if let Some ( obj) = entry_data ( entry_mode, id) ? {
54+ if let Some ( obj) = entry_data ( entry_mode. kind ( ) , id) ? {
4455 for line in obj. data . lines ( ) {
4556 let version = version_from_json_line ( line, change. location ) ?;
4657 let change = if version. yanked {
@@ -65,66 +76,82 @@ impl Delegate {
6576 } ) ;
6677 }
6778 }
68- Modification { .. } => {
69- if let Some ( diff) = change. event . diff ( ) . transpose ( ) ? {
70- let mut old_lines = AHashSet :: with_capacity ( 1024 ) ;
71- let location = change. location ;
72- for ( number, line) in diff. old . data . lines ( ) . enumerate ( ) {
73- old_lines. insert ( Line ( number, line) ) ;
74- }
79+ Modification { entry_mode, .. } => {
80+ if entry_mode. is_blob ( ) {
81+ self . resource_cache . clear_resource_cache ( ) ;
82+ let platform = change. diff ( & mut self . resource_cache ) ?;
83+ if let Some ( ( old, new) ) = platform. resource_cache . resources ( ) {
84+ let mut old_lines = AHashSet :: with_capacity ( 1024 ) ;
85+ let location = change. location ;
86+ for ( number, line) in old
87+ . data
88+ . as_slice ( )
89+ . expect ( "present in modification" )
90+ . lines ( )
91+ . enumerate ( )
92+ {
93+ old_lines. insert ( Line ( number, line) ) ;
94+ }
7595
76- // A RawTable is used to represent a Checksum -> CrateVersion map
77- // because the checksum is already stored in the CrateVersion
78- // and we want to avoid storing the checksum twice for performance reasons
79- let mut new_versions = RawTable :: with_capacity ( old_lines. len ( ) . min ( 1024 ) ) ;
80- let hasher = RandomState :: new ( ) ;
96+ // A RawTable is used to represent a Checksum -> CrateVersion map
97+ // because the checksum is already stored in the CrateVersion
98+ // and we want to avoid storing the checksum twice for performance reasons
99+ let mut new_versions = RawTable :: with_capacity ( old_lines. len ( ) . min ( 1024 ) ) ;
100+ let hasher = RandomState :: new ( ) ;
81101
82- for ( number, line) in diff. new . data . lines ( ) . enumerate ( ) {
83- // first quickly check if the exact same line is already present in this file in that case we don't need to do anything else
84- if old_lines. remove ( & Line ( number, line) ) {
85- continue ;
102+ for ( number, line) in new
103+ . data
104+ . as_slice ( )
105+ . expect ( "present in modification" )
106+ . lines ( )
107+ . enumerate ( )
108+ {
109+ // first quickly check if the exact same line is already present in this file in that case we don't need to do anything else
110+ if old_lines. remove ( & Line ( number, line) ) {
111+ continue ;
112+ }
113+ // no need to check if the checksum already exists in the hashmap
114+ // as each checksum appears only once
115+ let new_version = version_from_json_line ( line, location) ?;
116+ new_versions. insert (
117+ hasher. hash_one ( new_version. checksum ) ,
118+ ( number, new_version) ,
119+ |rehashed| hasher. hash_one ( rehashed. 1 . checksum ) ,
120+ ) ;
86121 }
87- // no need to check if the checksum already exists in the hashmap
88- // as each checksum appears only once
89- let new_version = version_from_json_line ( line, location) ?;
90- new_versions. insert (
91- hasher. hash_one ( new_version. checksum ) ,
92- ( number, new_version) ,
93- |rehashed| hasher. hash_one ( rehashed. 1 . checksum ) ,
94- ) ;
95- }
96122
97- for line in old_lines. drain ( ) {
98- let old_version = version_from_json_line ( & line, location) ?;
99- let new_version = new_versions
100- . remove_entry ( hasher. hash_one ( old_version. checksum ) , |version| {
101- version. 1 . checksum == old_version. checksum
102- } ) ;
103- match new_version {
104- Some ( ( _, new_version) ) => {
105- let change = match ( old_version. yanked , new_version. yanked ) {
106- ( true , false ) => Change :: Unyanked ( new_version) ,
107- ( false , true ) => Change :: Yanked ( new_version) ,
108- _ => continue ,
109- } ;
110- self . per_file_changes . push ( ( line. 0 , change) )
123+ for line in old_lines. drain ( ) {
124+ let old_version = version_from_json_line ( & line, location) ?;
125+ let new_version = new_versions
126+ . remove_entry ( hasher. hash_one ( old_version. checksum ) , |version| {
127+ version. 1 . checksum == old_version. checksum
128+ } ) ;
129+ match new_version {
130+ Some ( ( _, new_version) ) => {
131+ let change = match ( old_version. yanked , new_version. yanked ) {
132+ ( true , false ) => Change :: Unyanked ( new_version) ,
133+ ( false , true ) => Change :: Yanked ( new_version) ,
134+ _ => continue ,
135+ } ;
136+ self . per_file_changes . push ( ( line. 0 , change) )
137+ }
138+ None => self
139+ . per_file_changes
140+ . push ( ( line. 0 , Change :: VersionDeleted ( old_version) ) ) ,
111141 }
112- None => self
113- . per_file_changes
114- . push ( ( line. 0 , Change :: VersionDeleted ( old_version) ) ) ,
115142 }
143+ for ( number, version) in new_versions. drain ( ) {
144+ let change = if version. yanked {
145+ Change :: AddedAndYanked ( version)
146+ } else {
147+ Change :: Added ( version)
148+ } ;
149+ self . per_file_changes . push ( ( number, change) ) ;
150+ }
151+ self . per_file_changes . sort_by_key ( |t| t. 0 ) ;
152+ self . changes
153+ . extend ( self . per_file_changes . drain ( ..) . map ( |t| t. 1 ) ) ;
116154 }
117- for ( number, version) in new_versions. drain ( ) {
118- let change = if version. yanked {
119- Change :: AddedAndYanked ( version)
120- } else {
121- Change :: Added ( version)
122- } ;
123- self . per_file_changes . push ( ( number, change) ) ;
124- }
125- self . per_file_changes . sort_by_key ( |t| t. 0 ) ;
126- self . changes
127- . extend ( self . per_file_changes . drain ( ..) . map ( |t| t. 1 ) ) ;
128155 }
129156 }
130157 }
0 commit comments