Move git-tracking check into diff command.

This avoids shelling out twice per buffer: once to check whether git
knows about the file and once to perform the diff.  Now we simply do
both in one external call.

Profiling showed external calls to git taking ~20ms.  This doesn't seem
too bad but it adds up.
This commit is contained in:
Andy Stewart
2014-01-24 11:47:11 +01:00
parent 13a11f8935
commit f2e08dbeb3
3 changed files with 38 additions and 25 deletions

View File

@@ -4,17 +4,25 @@ let s:hunk_re = '^@@ -\(\d\+\),\?\(\d*\) +\(\d\+\),\?\(\d*\) @@'
function! diff#run_diff(realtime, use_external_grep) function! diff#run_diff(realtime, use_external_grep)
let cmd = 'git ls-files --error-unmatch' . utility#discard_stdout_and_stderr() . ' ' . shellescape(utility#file()) . ' && '
if a:realtime if a:realtime
let blob_name = ':./' . fnamemodify(utility#file(),':t') let blob_name = ':./' . fnamemodify(utility#file(),':t')
let blob_file = tempname() let blob_file = tempname()
let cmd = 'git show ' . blob_name . ' > ' . blob_file . ' && diff -U0 ' . g:gitgutter_diff_args . ' ' . blob_file . ' - ' let cmd .= 'git show ' . blob_name . ' > ' . blob_file .
\ ' && diff -U0 ' . g:gitgutter_diff_args . ' ' . blob_file . ' - '
else else
let cmd = 'git diff --no-ext-diff --no-color -U0 ' . g:gitgutter_diff_args . ' ' . shellescape(utility#file()) let cmd .= 'git diff --no-ext-diff --no-color -U0 ' . g:gitgutter_diff_args . ' ' . shellescape(utility#file())
endif endif
if a:use_external_grep && s:grep_available if a:use_external_grep && s:grep_available
let cmd .= s:grep_command " grep exits with 1 when no matches are found. However we want to treat
" non-matches as non-erroneous behaviour; so we append ` || :`.
let cmd .= s:grep_command . ' || :'
endif endif
let cmd = utility#escape(cmd) let cmd = utility#escape(cmd)
if a:realtime if a:realtime
if &fileformat ==# "dos" if &fileformat ==# "dos"
let eol = "\r\n" let eol = "\r\n"
@@ -28,6 +36,13 @@ function! diff#run_diff(realtime, use_external_grep)
else else
let diff = system(utility#command_in_directory_of_file(cmd)) let diff = system(utility#command_in_directory_of_file(cmd))
endif endif
if v:shell_error
" A shell error indicates the file is not tracked by git (unless something
" bizarre is going on).
throw 'git-diff failed'
endif
return diff return diff
endfunction endfunction

View File

@@ -1,7 +1,7 @@
let s:file = '' let s:file = ''
function! utility#is_active() function! utility#is_active()
return g:gitgutter_enabled && utility#exists_file() && utility#is_tracked_by_git() return g:gitgutter_enabled && utility#exists_file()
endfunction endfunction
function! utility#current_file() function! utility#current_file()
@@ -64,12 +64,6 @@ function! utility#command_in_directory_of_file(cmd)
return substitute(utility#cmd_in_dir, "'", '"', 'g') return substitute(utility#cmd_in_dir, "'", '"', 'g')
endfunction endfunction
function! utility#is_tracked_by_git()
let cmd = utility#escape('git ls-files --error-unmatch' . utility#discard_stdout_and_stderr() . ' ' . shellescape(utility#file()))
call system(utility#command_in_directory_of_file(cmd))
return !v:shell_error
endfunction
function! utility#differences(hunks) function! utility#differences(hunks)
return len(a:hunks) != 0 return len(a:hunks) != 0
endfunction endfunction

View File

@@ -55,26 +55,30 @@ command GitGutterAll call GitGutterAll()
function! GitGutter(file, realtime) function! GitGutter(file, realtime)
call utility#set_file(a:file) call utility#set_file(a:file)
if utility#is_active() if utility#is_active()
if !a:realtime || utility#has_fresh_changes(a:file) try
let diff = diff#run_diff(a:realtime || utility#has_unsaved_changes(a:file), 1) if !a:realtime || utility#has_fresh_changes(a:file)
let s:hunks = diff#parse_diff(diff) let diff = diff#run_diff(a:realtime || utility#has_unsaved_changes(a:file), 1)
let modified_lines = diff#process_hunks(s:hunks) let s:hunks = diff#parse_diff(diff)
let modified_lines = diff#process_hunks(s:hunks)
if g:gitgutter_signs if g:gitgutter_signs
if g:gitgutter_sign_column_always if g:gitgutter_sign_column_always
call sign#add_dummy_sign() call sign#add_dummy_sign()
else
if utility#differences(s:hunks)
call sign#add_dummy_sign() " prevent flicker
else else
call sign#remove_dummy_sign() if utility#differences(s:hunks)
call sign#add_dummy_sign() " prevent flicker
else
call sign#remove_dummy_sign()
endif
endif endif
call sign#update_signs(a:file, modified_lines)
endif endif
call sign#update_signs(a:file, modified_lines)
endif
call utility#save_last_seen_change(a:file) call utility#save_last_seen_change(a:file)
endif endif
catch /git-diff failed/
call hunk#reset()
endtry
else else
call hunk#reset() call hunk#reset()
endif endif