@@ -91,7 +91,7 @@ impl<'a, 'repo> Platform<'a, 'repo> {
9191 }
9292
9393 /// Provide `None` to disable rewrite tracking entirely, or pass `Some(<configuration>)` to control to
94- /// what extend rename and copy tracking is performed.
94+ /// what extent rename and copy tracking is performed.
9595 ///
9696 /// Note that by default, the git configuration determines rewrite tracking and git defaults are used
9797 /// if nothing is configured, which turns rename tracking with 50% similarity on, while not tracking copies at all.
@@ -101,6 +101,73 @@ impl<'a, 'repo> Platform<'a, 'repo> {
101101 }
102102}
103103
104+ /// Provide aggregated information of a diff between two trees.
105+ #[ derive( Default , Debug , Copy , Clone , Ord , PartialOrd , Eq , PartialEq , Hash ) ]
106+ #[ doc( alias = "DiffStats" , alias = "git2" ) ]
107+ pub struct Stats {
108+ /// The total amount of lines added in the between blobs of the two trees.
109+ #[ doc( alias = "insertions" , alias = "git2" ) ]
110+ pub lines_added : u64 ,
111+ /// The total amount of lines removed in the between blobs of the two trees.
112+ #[ doc( alias = "deletions" , alias = "git2" ) ]
113+ pub lines_removed : u64 ,
114+ /// The number of files that contributed to these statistics as they were added, removed or modified.
115+ pub files_changed : u64 ,
116+ }
117+
118+ ///
119+ #[ allow( clippy:: empty_docs) ]
120+ pub mod stats {
121+ /// The error returned by [`stats()`](super::Platform::stats()).
122+ #[ derive( Debug , thiserror:: Error ) ]
123+ #[ allow( missing_docs) ]
124+ pub enum Error {
125+ #[ error( transparent) ]
126+ CreateResourceCache ( #[ from] crate :: repository:: diff:: resource_cache:: Error ) ,
127+ #[ error( transparent) ]
128+ ForEachChange ( #[ from] crate :: object:: tree:: diff:: for_each:: Error ) ,
129+ }
130+ }
131+
132+ /// Convenience
133+ impl < ' a , ' repo > Platform < ' a , ' repo > {
134+ /// Calculate statistics about the lines of the diff between our current and the `other` tree.
135+ ///
136+ /// ### Performance Notes
137+ ///
138+ /// Be sure to forcefully disable [`track_rewrites(None)`](Self::track_rewrites) to avoid
139+ /// rename tracking, an operation that doesn't affect the statistics currently.
140+ /// As diffed resources aren't cached, if highly repetitive blobs are expected, performance
141+ /// may be diminished. In real-world scenarios where blobs are mostly unique, that's not an issue though.
142+ pub fn stats ( & mut self , other : & Tree < ' _ > ) -> Result < Stats , stats:: Error > {
143+ // let (mut number_of_files, mut lines_added, mut lines_removed) = (0, 0, 0);
144+ let mut resource_cache = self . lhs . repo . diff_resource_cache_for_tree_diff ( ) ?;
145+
146+ let ( mut files_changed, mut lines_added, mut lines_removed) = ( 0 , 0 , 0 ) ;
147+ self . for_each_to_obtain_tree ( other, |change| {
148+ if let Some ( counts) = change
149+ . diff ( & mut resource_cache)
150+ . ok ( )
151+ . and_then ( |mut platform| platform. line_counts ( ) . ok ( ) )
152+ . flatten ( )
153+ {
154+ files_changed += 1 ;
155+ lines_added += counts. insertions as u64 ;
156+ lines_removed += counts. removals as u64 ;
157+ }
158+
159+ resource_cache. clear_resource_cache ( ) ;
160+ Ok :: < _ , std:: convert:: Infallible > ( Action :: Continue )
161+ } ) ?;
162+
163+ Ok ( Stats {
164+ files_changed,
165+ lines_added,
166+ lines_removed,
167+ } )
168+ }
169+ }
170+
104171///
105172#[ allow( clippy:: empty_docs) ]
106173pub mod for_each;
0 commit comments