@@ -166,7 +166,40 @@ M.status = function(base, exclude_directories, path)
166
166
return context .git_status , git_root
167
167
end
168
168
169
- M .status_async = function (path , base )
169
+ local function parse_lines_batch (context , job_complete_callback )
170
+ if context .lines_total == nil then
171
+ context .lines_total = math.min (context .max_lines , # context .lines )
172
+ context .lines_parsed = 0
173
+ if context .lines_total == 0 then
174
+ if type (job_complete_callback ) == " function" then
175
+ job_complete_callback ()
176
+ end
177
+ return
178
+ end
179
+ -- don't do anything on the first batch, we just finished what might have been
180
+ -- a lot of work in gathering these lines...
181
+ else
182
+ local batch_size = math.min (context .batch_size , context .lines_total - context .lines_parsed )
183
+ local i = 0
184
+ while i < batch_size do
185
+ i = i + 1
186
+ parse_git_status_line (context , context .lines [context .lines_parsed + 1 ])
187
+ end
188
+ end
189
+
190
+ if context .lines_parsed >= context .lines_total then
191
+ if type (job_complete_callback ) == " function" then
192
+ job_complete_callback ()
193
+ end
194
+ else
195
+ -- add small delay so other work can happen
196
+ vim .defer_fn (function ()
197
+ parse_lines_batch (context , job_complete_callback )
198
+ end , context .batch_delay )
199
+ end
200
+ end
201
+
202
+ M .status_async = function (path , base , opts )
170
203
local git_root = git_utils .get_repository_root (path )
171
204
if utils .truthy (git_root ) then
172
205
log .trace (" git.status.status_async called" )
@@ -175,13 +208,28 @@ M.status_async = function(path, base)
175
208
return false
176
209
end
177
210
211
+ local event_id = " git_status_" .. git_root
178
212
local context = {
179
213
git_root = git_root ,
180
214
git_status = {},
181
215
exclude_directories = false ,
182
- lines_parsed = 0
216
+ lines = {},
217
+ lines_parsed = 0 ,
218
+ batch_size = opts .batch_size or 1000 ,
219
+ batch_delay = opts .batch_delay or 10 ,
220
+ max_lines = opts .max_lines or 100000 ,
183
221
}
184
222
223
+ local job_complete_callback = function ()
224
+ utils .debounce (event_id , nil , nil , nil , utils .debounce_action .COMPLETE_ASYNC_JOB )
225
+ vim .schedule (function ()
226
+ events .fire_event (events .GIT_STATUS_CHANGED , {
227
+ git_root = context .git_root ,
228
+ git_status = context .git_status ,
229
+ })
230
+ end )
231
+ end
232
+
185
233
local should_process = function (err , line , job , err_msg )
186
234
if vim .v .dying > 0 or vim .v .exiting ~= vim .NIL then
187
235
job :shutdown ()
@@ -194,16 +242,16 @@ M.status_async = function(path, base)
194
242
return true
195
243
end
196
244
197
- local event_id = " git_status_" .. git_root
198
245
utils .debounce (event_id , function ()
199
246
local staged_job = Job
200
247
:new ({
201
248
command = " git" ,
202
249
args = { " -C" , git_root , " diff" , " --staged" , " --name-status" , base , " --" },
203
250
enable_recording = false ,
251
+ maximium_results = context .max_lines ,
204
252
on_stdout = vim .schedule_wrap (function (err , line , job )
205
253
if should_process (err , line , job , " status_async staged error:" ) then
206
- parse_git_status_line (context , line )
254
+ table.insert (context . lines , line )
207
255
end
208
256
end ),
209
257
on_stderr = function (err , line )
@@ -221,12 +269,13 @@ M.status_async = function(path, base)
221
269
command = " git" ,
222
270
args = { " -C" , git_root , " diff" , " --name-status" },
223
271
enable_recording = false ,
272
+ maximium_results = context .max_lines ,
224
273
on_stdout = vim .schedule_wrap (function (err , line , job )
225
274
if should_process (err , line , job , " status_async unstaged error:" ) then
226
275
if line then
227
276
line = " " .. line
228
277
end
229
- parse_git_status_line (context , line )
278
+ table.insert (context . lines , line )
230
279
end
231
280
end ),
232
281
on_stderr = function (err , line )
@@ -244,12 +293,13 @@ M.status_async = function(path, base)
244
293
command = " git" ,
245
294
args = { " -C" , git_root , " ls-files" , " --exclude-standard" , " --others" },
246
295
enable_recording = false ,
296
+ maximium_results = context .max_lines ,
247
297
on_stdout = vim .schedule_wrap (function (err , line , job )
248
298
if should_process (err , line , job , " status_async untracked error:" ) then
249
299
if line then
250
300
line = " ? " .. line
251
301
end
252
- parse_git_status_line (context , line )
302
+ table.insert (context . lines , line )
253
303
end
254
304
end ),
255
305
on_stderr = function (err , line )
@@ -258,14 +308,8 @@ M.status_async = function(path, base)
258
308
end
259
309
end ,
260
310
on_exit = function (_ , return_val )
261
- utils .debounce (event_id , nil , nil , nil , utils .debounce_action .COMPLETE_ASYNC_JOB )
262
311
log .trace (" status_async untracked completed with return_val:" , return_val , " ;" , context .lines_parsed , " lines parsed" )
263
- vim .schedule (function ()
264
- events .fire_event (events .GIT_STATUS_CHANGED , {
265
- git_root = context .git_root ,
266
- git_status = context .git_status ,
267
- })
268
- end )
312
+ parse_lines_batch (context , job_complete_callback )
269
313
end ,
270
314
})
271
315
0 commit comments