@@ -6,24 +6,35 @@ use hashbrown::raw::RawTable;
6
6
use std:: hash:: Hasher ;
7
7
use std:: ops:: Deref ;
8
8
9
- #[ derive( Default ) ]
10
9
pub ( crate ) struct Delegate {
11
10
changes : Vec < Change > ,
11
+ resource_cache : gix:: diff:: blob:: Platform ,
12
12
/// All changes that happen within a file, along the line-number it happens in .
13
13
per_file_changes : Vec < ( usize , Change ) > ,
14
14
err : Option < Error > ,
15
15
}
16
16
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
+
17
28
impl Delegate {
18
29
pub fn handle (
19
30
& mut self ,
20
31
change : gix:: object:: tree:: diff:: Change < ' _ , ' _ , ' _ > ,
21
32
) -> Result < gix:: object:: tree:: diff:: Action , Error > {
22
33
use gix:: bstr:: ByteSlice ;
23
34
use gix:: object:: tree:: diff:: change:: Event :: * ;
24
- use gix:: objs:: tree:: EntryMode :: * ;
35
+ use gix:: objs:: tree:: EntryKind :: * ;
25
36
fn entry_data (
26
- entry : gix:: objs:: tree:: EntryMode ,
37
+ entry : gix:: objs:: tree:: EntryKind ,
27
38
id : gix:: Id < ' _ > ,
28
39
) -> Result < Option < gix:: Object < ' _ > > , Error > {
29
40
matches ! ( entry, Blob | BlobExecutable )
@@ -40,7 +51,7 @@ impl Delegate {
40
51
unreachable ! ( "BUG: this is disabled so shouldn't happen" )
41
52
}
42
53
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) ? {
44
55
for line in obj. data . lines ( ) {
45
56
let version = version_from_json_line ( line, change. location ) ?;
46
57
let change = if version. yanked {
@@ -65,66 +76,82 @@ impl Delegate {
65
76
} ) ;
66
77
}
67
78
}
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
+ }
75
95
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 ( ) ;
81
101
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
+ ) ;
86
121
}
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
- }
96
122
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) ) ) ,
111
141
}
112
- None => self
113
- . per_file_changes
114
- . push ( ( line. 0 , Change :: VersionDeleted ( old_version) ) ) ,
115
142
}
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 ) ) ;
116
154
}
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 ) ) ;
128
155
}
129
156
}
130
157
}
0 commit comments