@@ -24,6 +24,8 @@ pub enum Error {
24
24
PeelToTree ( #[ from] git:: object:: peel:: to_kind:: Error ) ,
25
25
#[ error( transparent) ]
26
26
Diff ( #[ from] git:: diff:: tree:: changes:: Error ) ,
27
+ #[ error( transparent) ]
28
+ VersionDecode ( #[ from] serde_json:: Error ) ,
27
29
}
28
30
29
31
/// Find changes without modifying the underling repository
@@ -160,7 +162,6 @@ impl Index {
160
162
from : impl Into < git:: hash:: ObjectId > ,
161
163
to : impl Into < git:: hash:: ObjectId > ,
162
164
) -> Result < Vec < Change > , Error > {
163
- let changes = Vec :: new ( ) ;
164
165
self . repo . object_cache_size_if_unset ( 4 * 1024 * 1024 ) ;
165
166
let into_tree = |id : git:: hash:: ObjectId | -> Result < git:: Tree < ' _ > , Error > {
166
167
Ok ( id
@@ -171,36 +172,97 @@ impl Index {
171
172
} ;
172
173
let from = into_tree ( from. into ( ) ) ?;
173
174
let to = into_tree ( to. into ( ) ) ?;
174
- struct Delegate ;
175
- impl git:: diff:: tree:: Visit for Delegate {
176
- fn pop_front_tracked_path_and_set_current ( & mut self ) {
177
- todo ! ( )
178
- }
179
-
180
- fn push_back_tracked_path_component ( & mut self , _component : & BStr ) {
181
- todo ! ( )
175
+ struct Delegate < ' repo > {
176
+ changes : Vec < Change > ,
177
+ err : Option < Error > ,
178
+ repo : & ' repo git:: Repository ,
179
+ }
180
+ impl < ' repo > Delegate < ' repo > {
181
+ fn from_repo ( repo : & ' repo git:: Repository ) -> Self {
182
+ Delegate {
183
+ changes : Vec :: new ( ) ,
184
+ err : None ,
185
+ repo,
186
+ }
182
187
}
183
-
184
- fn push_path_component ( & mut self , _component : & BStr ) {
185
- todo ! ( )
188
+ fn handle ( & mut self , change : git:: diff:: tree:: visit:: Change ) -> Result < ( ) , Error > {
189
+ use git:: diff:: tree:: visit:: Change :: * ;
190
+ use git:: objs:: tree:: EntryMode :: * ;
191
+ fn entry_data (
192
+ repo : & git:: Repository ,
193
+ entry : git:: objs:: tree:: EntryMode ,
194
+ oid : git:: hash:: ObjectId ,
195
+ ) -> Result < Option < git:: Object < ' _ > > , Error > {
196
+ matches ! ( entry, Blob | BlobExecutable )
197
+ . then ( || repo. find_object ( oid) )
198
+ . transpose ( )
199
+ . map_err ( Into :: into)
200
+ }
201
+ use git:: bstr:: ByteSlice ;
202
+ match change {
203
+ Addition { entry_mode, oid } => {
204
+ if let Some ( obj) = entry_data ( self . repo , entry_mode, oid) ? {
205
+ for line in ( & obj. data ) . lines ( ) {
206
+ self . changes . push ( Change :: Added ( serde_json:: from_slice :: <
207
+ CrateVersion ,
208
+ > (
209
+ line
210
+ ) ?) ) ;
211
+ }
212
+ }
213
+ }
214
+ Deletion { entry_mode, oid } => {
215
+ if let Some ( _obj) = entry_data ( self . repo , entry_mode, oid) ? {
216
+ todo ! ( "deletion" )
217
+ }
218
+ }
219
+ Modification {
220
+ previous_entry_mode : _,
221
+ previous_oid : _,
222
+ entry_mode : _,
223
+ oid : _,
224
+ } => {
225
+ todo ! ( "modification" )
226
+ }
227
+ }
228
+ Ok ( ( ) )
186
229
}
187
-
188
- fn pop_path_component ( & mut self ) {
189
- todo ! ( )
230
+ fn into_result ( self ) -> Result < Vec < Change > , Error > {
231
+ match self . err {
232
+ Some ( err) => Err ( err) ,
233
+ None => Ok ( self . changes ) ,
234
+ }
190
235
}
236
+ }
237
+ impl git:: diff:: tree:: Visit for Delegate < ' _ > {
238
+ fn pop_front_tracked_path_and_set_current ( & mut self ) { }
239
+ fn push_back_tracked_path_component ( & mut self , _component : & BStr ) { }
240
+ fn push_path_component ( & mut self , _component : & BStr ) { }
241
+ fn pop_path_component ( & mut self ) { }
191
242
192
- fn visit ( & mut self , _change : git:: diff:: tree:: visit:: Change ) -> Action {
193
- todo ! ( )
243
+ fn visit ( & mut self , change : git:: diff:: tree:: visit:: Change ) -> Action {
244
+ match self . handle ( change) {
245
+ Ok ( ( ) ) => Action :: Continue ,
246
+ Err ( err) => {
247
+ self . err = err. into ( ) ;
248
+ Action :: Cancel
249
+ }
250
+ }
194
251
}
195
252
}
196
- git:: objs:: TreeRefIter :: from_bytes ( & from. data ) . changes_needed (
253
+
254
+ let mut delegate = Delegate :: from_repo ( & self . repo ) ;
255
+ let file_changes = git:: objs:: TreeRefIter :: from_bytes ( & from. data ) . changes_needed (
197
256
git:: objs:: TreeRefIter :: from_bytes ( & to. data ) ,
198
257
git:: diff:: tree:: State :: default ( ) ,
199
258
|id, buf| self . repo . objects . find_tree_iter ( id, buf) . ok ( ) ,
200
- & mut Delegate ,
201
- ) ?;
202
-
203
- Ok ( changes)
259
+ & mut delegate,
260
+ ) ;
261
+ match file_changes. err ( ) {
262
+ None | Some ( git:: diff:: tree:: changes:: Error :: Cancelled ) => { /*error in delegate*/ }
263
+ Some ( err) => return Err ( err. into ( ) ) ,
264
+ }
265
+ delegate. into_result ( )
204
266
}
205
267
}
206
268
0 commit comments