@@ -293,18 +293,33 @@ impl Repository {
293293 . join ( Self :: relative_index_file ( name) )
294294 }
295295
296+ /// Returns the relative path to the crate index file.
297+ /// Does not perform conversion to lowercase.
298+ fn relative_index_file_helper ( name : & str ) -> Vec < & str > {
299+ match name. len ( ) {
300+ 1 => vec ! [ "1" , name] ,
301+ 2 => vec ! [ "2" , name] ,
302+ 3 => vec ! [ "3" , & name[ ..1 ] , name] ,
303+ _ => vec ! [ & name[ 0 ..2 ] , & name[ 2 ..4 ] , name] ,
304+ }
305+ }
306+
296307 /// Returns the relative path to the crate index file that corresponds to
297- /// the given crate name.
308+ /// the given crate name as a path (i.e. with platform-dependent folder separators) .
298309 ///
299310 /// see <https://doc.rust-lang.org/cargo/reference/registries.html#index-format>
300311 pub fn relative_index_file ( name : & str ) -> PathBuf {
301312 let name = name. to_lowercase ( ) ;
302- match name. len ( ) {
303- 1 => Path :: new ( "1" ) . join ( & name) ,
304- 2 => Path :: new ( "2" ) . join ( & name) ,
305- 3 => Path :: new ( "3" ) . join ( & name[ ..1 ] ) . join ( & name) ,
306- _ => Path :: new ( & name[ 0 ..2 ] ) . join ( & name[ 2 ..4 ] ) . join ( & name) ,
307- }
313+ Self :: relative_index_file_helper ( & name) . iter ( ) . collect ( )
314+ }
315+
316+ /// Returns the relative path to the crate index file that corresponds to
317+ /// the given crate name for usage in URLs (i.e. with `/` separator).
318+ ///
319+ /// see <https://doc.rust-lang.org/cargo/reference/registries.html#index-format>
320+ pub fn relative_index_file_for_url ( name : & str ) -> String {
321+ let name = name. to_lowercase ( ) ;
322+ Self :: relative_index_file_helper ( & name) . join ( "/" )
308323 }
309324
310325 /// Returns the [Object ID](git2::Oid) of the currently checked out commit
@@ -343,6 +358,50 @@ impl Repository {
343358 self . push ( "refs/heads/master" )
344359 }
345360
361+ /// Gets a list of files that have been modified since a given `starting_commit`
362+ /// (use `starting_commit = None` for a list of all files).
363+ pub fn get_files_modified_since (
364+ & self ,
365+ starting_commit : Option < & str > ,
366+ ) -> anyhow:: Result < Vec < PathBuf > > {
367+ let starting_commit = match starting_commit {
368+ Some ( starting_commit) => {
369+ let oid = git2:: Oid :: from_str ( starting_commit)
370+ . context ( "failed to parse commit into Oid" ) ?;
371+ let commit = self
372+ . repository
373+ . find_commit ( oid)
374+ . context ( "failed to find commit" ) ?;
375+ Some (
376+ commit
377+ . as_object ( )
378+ . peel_to_tree ( )
379+ . context ( "failed to find tree for commit" ) ?,
380+ )
381+ }
382+ None => None ,
383+ } ;
384+
385+ let head = self
386+ . repository
387+ . find_commit ( self . head_oid ( ) ?) ?
388+ . as_object ( )
389+ . peel_to_tree ( )
390+ . context ( "failed to find tree for HEAD" ) ?;
391+ let diff = self
392+ . repository
393+ . diff_tree_to_tree ( starting_commit. as_ref ( ) , Some ( & head) , None )
394+ . context ( "failed to run diff" ) ?;
395+ let files = diff
396+ . deltas ( )
397+ . map ( |delta| delta. new_file ( ) )
398+ . filter ( |file| file. exists ( ) )
399+ . map ( |file| file. path ( ) . unwrap ( ) . to_path_buf ( ) )
400+ . collect ( ) ;
401+
402+ Ok ( files)
403+ }
404+
346405 /// Push the current branch to the provided refname
347406 fn push ( & self , refspec : & str ) -> anyhow:: Result < ( ) > {
348407 let mut ref_status = Ok ( ( ) ) ;
0 commit comments