@@ -24,6 +24,8 @@ pub enum Error {
2424 PeelToTree ( #[ from] git:: object:: peel:: to_kind:: Error ) ,
2525 #[ error( transparent) ]
2626 Diff ( #[ from] git:: diff:: tree:: changes:: Error ) ,
27+ #[ error( transparent) ]
28+ VersionDecode ( #[ from] serde_json:: Error ) ,
2729}
2830
2931/// Find changes without modifying the underling repository
@@ -160,7 +162,6 @@ impl Index {
160162 from : impl Into < git:: hash:: ObjectId > ,
161163 to : impl Into < git:: hash:: ObjectId > ,
162164 ) -> Result < Vec < Change > , Error > {
163- let changes = Vec :: new ( ) ;
164165 self . repo . object_cache_size_if_unset ( 4 * 1024 * 1024 ) ;
165166 let into_tree = |id : git:: hash:: ObjectId | -> Result < git:: Tree < ' _ > , Error > {
166167 Ok ( id
@@ -171,36 +172,97 @@ impl Index {
171172 } ;
172173 let from = into_tree ( from. into ( ) ) ?;
173174 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+ }
182187 }
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 ( ( ) )
186229 }
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+ }
190235 }
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 ) { }
191242
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+ }
194251 }
195252 }
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 (
197256 git:: objs:: TreeRefIter :: from_bytes ( & to. data ) ,
198257 git:: diff:: tree:: State :: default ( ) ,
199258 |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 ( )
204266 }
205267}
206268
0 commit comments