@@ -8,26 +8,25 @@ use std::{
8
8
use git2:: { Diff , DiffFindOptions , DiffOptions , Repository } ;
9
9
use parking_lot:: { Mutex , RwLock } ;
10
10
11
- use crate :: git:: {
12
- Commit ,
13
- CommitDiff ,
14
- CommitDiffLoaderOptions ,
15
- Delta ,
16
- DiffLine ,
17
- FileMode ,
18
- FileStatus ,
19
- FileStatusBuilder ,
20
- GitError ,
21
- Status ,
22
- commit_diff:: LoadedStatus ,
11
+ use crate :: {
12
+ diff:: { CommitDiff , CommitDiffLoaderOptions , LoadStatus } ,
13
+ git:: { Commit , Delta , DiffLine , FileMode , FileStatus , FileStatusBuilder , GitError , Status } ,
23
14
} ;
24
15
25
16
static UNKNOWN_PATH : LazyLock < PathBuf > = LazyLock :: new ( || PathBuf :: from ( "unknown" ) ) ;
26
- const LONG_DIFF_TIME : Duration = Duration :: from_millis ( 100 ) ;
27
17
28
- pub ( crate ) trait UpdateHandlerFn : Fn ( ) -> bool + Sync + Send { }
18
+ pub ( crate ) trait DiffUpdateHandlerFn : Fn ( LoadStatus ) -> bool + Sync + Send { }
29
19
30
- impl < FN : Fn ( ) -> bool + Sync + Send > UpdateHandlerFn for FN { }
20
+ impl < FN : Fn ( LoadStatus ) -> bool + Sync + Send > DiffUpdateHandlerFn for FN { }
21
+
22
+ fn create_status_update ( quick : bool , processed_files : usize , total_files : usize ) -> LoadStatus {
23
+ if quick {
24
+ LoadStatus :: QuickDiff ( processed_files, total_files)
25
+ }
26
+ else {
27
+ LoadStatus :: Diff ( processed_files, total_files)
28
+ }
29
+ }
31
30
32
31
pub ( crate ) struct CommitDiffLoader {
33
32
config : CommitDiffLoaderOptions ,
@@ -91,7 +90,7 @@ impl CommitDiffLoader {
91
90
fn diff < ' r > (
92
91
repository : & ' r Repository ,
93
92
config : & CommitDiffLoaderOptions ,
94
- commit : & git2:: Commit ,
93
+ commit : & git2:: Commit < ' _ > ,
95
94
diff_options : & mut DiffOptions ,
96
95
) -> Result < Diff < ' r > , GitError > {
97
96
_ = diff_options
@@ -118,12 +117,13 @@ impl CommitDiffLoader {
118
117
. map_err ( |e| GitError :: DiffLoad { cause : e } )
119
118
}
120
119
121
- pub ( crate ) fn load_diff ( & mut self , hash : & str , update_notifier : impl UpdateHandlerFn ) -> Result < ( ) , GitError > {
122
- let mut commit_diff = self . commit_diff . write ( ) ;
123
- commit_diff. reset ( self . find_commit ( hash) ?, self . find_first_parent ( hash) ?) ;
124
- drop ( commit_diff) ;
125
- if update_notifier ( ) {
126
- return Ok ( ( ) ) ;
120
+ pub ( crate ) fn load_diff ( & mut self , hash : & str , update_notifier : impl DiffUpdateHandlerFn ) -> Result < ( ) , GitError > {
121
+ {
122
+ let mut commit_diff = self . commit_diff . write ( ) ;
123
+ commit_diff. reset ( self . find_commit ( hash) ?, self . find_first_parent ( hash) ?) ;
124
+ if update_notifier ( LoadStatus :: New ) {
125
+ return Ok ( ( ) ) ;
126
+ }
127
127
}
128
128
129
129
// TODO, duplicated with find_commit function
@@ -144,20 +144,23 @@ impl CommitDiffLoader {
144
144
145
145
let stats = diff. stats ( ) . map_err ( |e| GitError :: DiffLoad { cause : e } ) ?;
146
146
147
- std:: thread:: sleep ( std:: time:: Duration :: from_millis ( 3_000 ) ) ;
148
- // when a diff contains a lot of track files, collecting the diff information can take upwards
149
- // of a minute. This performs a quicker diff, that does not detect copies and renames against
150
- // unmodified files.
147
+ // std::thread::sleep(std::time::Duration::from_millis(3_000));
148
+ // when a diff contains a lot of untracked files, collecting the diff information can take
149
+ // upwards of a minute. This performs a quicker diff, that does not detect copies and
150
+ // renames against unmodified files.
151
151
if self . config . copies && stats. files_changed ( ) > 1 {
152
152
// self.config.quick_diff_threshold {
153
- let mut diff_options = DiffOptions :: new ( ) ;
154
- let quick_diff = Self :: diff ( & self . repository , & self . config , & commit, & mut diff_options) ?;
155
- self . collect ( & quick_diff, LoadedStatus :: Partial ) ?;
156
- if update_notifier ( ) {
153
+ self . collect (
154
+ & Self :: diff ( & self . repository , & self . config , & commit, & mut DiffOptions :: new ( ) ) ?,
155
+ & update_notifier,
156
+ true ,
157
+ ) ?;
158
+
159
+ if update_notifier ( LoadStatus :: CompleteQuickDiff ) {
157
160
return Ok ( ( ) ) ;
158
161
}
159
162
}
160
- std:: thread:: sleep ( std:: time:: Duration :: from_millis ( 3_000 ) ) ;
163
+ // std::thread::sleep(std::time::Duration::from_millis(3_000));
161
164
162
165
let mut diff_find_options = DiffFindOptions :: new ( ) ;
163
166
_ = diff_find_options
@@ -170,9 +173,10 @@ impl CommitDiffLoader {
170
173
171
174
diff. find_similar ( Some ( & mut diff_find_options) )
172
175
. map_err ( |e| GitError :: DiffLoad { cause : e } ) ?;
173
- self . collect ( & diff, LoadedStatus :: Complete ) ?;
176
+ self . collect ( & diff, & update_notifier , false ) ?;
174
177
175
- if update_notifier ( ) {
178
+ if update_notifier ( LoadStatus :: DiffComplete ) {
179
+ _ = update_notifier ( LoadStatus :: Canceled ) ;
176
180
return Ok ( ( ) ) ;
177
181
}
178
182
Ok ( ( ) )
@@ -183,7 +187,8 @@ impl CommitDiffLoader {
183
187
pub ( crate ) fn collect (
184
188
& self ,
185
189
diff : & Diff < ' _ > ,
186
- update_handler : UpdateHandlerFn ,
190
+ update_handler : & impl DiffUpdateHandlerFn ,
191
+ quick : bool ,
187
192
) -> Result < ( ) , GitError > {
188
193
let file_stats_builder = Mutex :: new ( FileStatusBuilder :: new ( ) ) ;
189
194
let mut unmodified_file_count: usize = 0 ;
@@ -192,6 +197,11 @@ impl CommitDiffLoader {
192
197
let stats = diff. stats ( ) . map_err ( |e| GitError :: DiffLoad { cause : e } ) ?;
193
198
let total_files_changed = stats. files_changed ( ) ;
194
199
200
+ if update_handler ( create_status_update ( quick, 0 , total_files_changed) ) {
201
+ return Ok ( ( ) ) ;
202
+ }
203
+ let mut time = Instant :: now ( ) ;
204
+
195
205
let collect_result = diff. foreach (
196
206
& mut |diff_delta, _| {
197
207
change_count += 1 ;
@@ -200,11 +210,10 @@ impl CommitDiffLoader {
200
210
unmodified_file_count += 1 ;
201
211
return true ;
202
212
}
203
- if change_count % 10 == 0 {
204
- let mut commit_diff = self . commit_diff . write ( ) ;
205
- commit_diff. update_status ( LoadedStatus :: Partial ( change_count, total_files_changed) )
206
- // early exit
207
- if update_handler ( ) {
213
+ if time. elapsed ( ) > Duration :: from_millis ( 10 ) {
214
+ time = Instant :: now ( ) ;
215
+ // std::thread::sleep(std::time::Duration::from_millis(500));
216
+ if update_handler ( create_status_update ( quick, change_count, total_files_changed) ) {
208
217
return false ;
209
218
}
210
219
}
@@ -247,23 +256,16 @@ impl CommitDiffLoader {
247
256
248
257
// error caused by early return
249
258
if collect_result. is_err ( ) {
250
- commit_diff. update_status ( LoadedStatus :: Canceled ) ;
251
- update_handler ( ) ;
259
+ _ = update_handler ( LoadStatus :: Canceled ) ;
252
260
return Ok ( ( ) ) ;
253
261
}
254
262
255
263
let number_files_changed = total_files_changed - unmodified_file_count;
256
264
let number_insertions = stats. insertions ( ) ;
257
265
let number_deletions = stats. deletions ( ) ;
258
266
259
- eprintln ! ( "Changes: {} {}" , change_count, stats. files_changed( ) ) ;
260
267
let fsb = file_stats_builder. into_inner ( ) ;
261
- commit_diff. update (
262
- fsb. build ( ) ,
263
- number_files_changed,
264
- number_insertions,
265
- number_deletions,
266
- ) ;
268
+ commit_diff. update ( fsb. build ( ) , number_files_changed, number_insertions, number_deletions) ;
267
269
Ok ( ( ) )
268
270
}
269
271
}
0 commit comments