diff --git a/autoload/gitgutter.vim b/autoload/gitgutter.vim index 1a4a2cf..65b40e8 100644 --- a/autoload/gitgutter.vim +++ b/autoload/gitgutter.vim @@ -41,7 +41,7 @@ function! gitgutter#process_buffer(bufnr, force) abort let diff = '' try - let diff = gitgutter#diff#run_diff(a:bufnr, 0) + let diff = gitgutter#diff#run_diff(a:bufnr, 'index', 0) catch /gitgutter not tracked/ call gitgutter#debug#log('Not tracked: '.gitgutter#utility#file(a:bufnr)) catch /gitgutter diff failed/ diff --git a/autoload/gitgutter/diff.vim b/autoload/gitgutter/diff.vim index 356a3b0..4e1ec66 100644 --- a/autoload/gitgutter/diff.vim +++ b/autoload/gitgutter/diff.vim @@ -11,10 +11,16 @@ endfunction let s:c_flag = s:git_supports_command_line_config_override() -let s:temp_index = tempname() +let s:temp_from = tempname() let s:temp_buffer = tempname() -" Returns a diff of the buffer. +" Returns a diff of the buffer against the index or the working tree. +" +" After running the diff we pass it through grep where available to reduce +" subsequent processing by the plugin. If grep is not available the plugin +" does the filtering instead. +" +" When diffing against the index: " " The buffer contents is not the same as the file on disk so we need to pass " two instances of the file to git-diff: @@ -27,11 +33,6 @@ let s:temp_buffer = tempname() " " and myfileB is the buffer contents. " -" After running the diff we pass it through grep where available to reduce -" subsequent processing by the plugin. If grep is not available the plugin -" does the filtering instead. -" -" " Regarding line endings: " " git-show does not convert line endings. @@ -57,7 +58,15 @@ let s:temp_buffer = tempname() " When writing the temporary files we preserve the original file's extension " so that repos using .gitattributes to control EOL conversion continue to " convert correctly. -function! gitgutter#diff#run_diff(bufnr, preserve_full_diff) abort +" +" Arguments: +" +" bufnr - the number of the buffer to be diffed +" from - 'index' or 'working_tree'; what the buffer is diffed against +" preserve_full_diff - truthy to return the full diff or falsey to return only +" the hunk headers (@@ -x,y +m,n @@); only possible if +" grep is available. +function! gitgutter#diff#run_diff(bufnr, from, preserve_full_diff) abort while gitgutter#utility#repo_path(a:bufnr, 0) == -1 sleep 5m endwhile @@ -66,18 +75,13 @@ function! gitgutter#diff#run_diff(bufnr, preserve_full_diff) abort throw 'gitgutter not tracked' endif - " Wrap compound commands in parentheses to make Windows happy. " bash doesn't mind the parentheses. let cmd = '(' - " Append buffer number to avoid race conditions between writing and reading - " the files when asynchronously processing multiple buffers. - " - " Without the buffer number, index_file would have a race in the shell - " between the second process writing it (with git-show) and the first - " reading it (with git-diff). - let index_file = s:temp_index.'.'.a:bufnr + " Append buffer number to temp filenames to avoid race conditions between + " writing and reading the files when asynchronously processing multiple + " buffers. " Without the buffer number, buff_file would have a race between the " second gitgutter#process_buffer() writing the file (synchronously, below) @@ -87,26 +91,39 @@ function! gitgutter#diff#run_diff(bufnr, preserve_full_diff) abort let extension = gitgutter#utility#extension(a:bufnr) if !empty(extension) - let index_file .= '.'.extension let buff_file .= '.'.extension endif - " Write file from index to temporary file. - let index_name = g:gitgutter_diff_base.':'.gitgutter#utility#repo_path(a:bufnr, 1) - let cmd .= g:gitgutter_git_executable.' --no-pager show '.index_name.' > '.index_file.' && ' - " Write buffer to temporary file. " Note: this is synchronous. call s:write_buffer(a:bufnr, buff_file) - " Call git-diff with the temporary files. + if a:from ==# 'index' + " Without the buffer number, from_file would have a race in the shell + " between the second process writing it (with git-show) and the first + " reading it (with git-diff). + let from_file = s:temp_from.'.'.a:bufnr + + if !empty(extension) + let from_file .= '.'.extension + endif + + " Write file from index to temporary file. + let index_name = g:gitgutter_diff_base.':'.gitgutter#utility#repo_path(a:bufnr, 1) + let cmd .= g:gitgutter_git_executable.' --no-pager show '.index_name.' > '.from_file.' && ' + + elseif a:from ==# 'working_tree' + let from_file = gitgutter#utility#repo_path(a:bufnr, 1) + endif + + " Call git-diff. let cmd .= g:gitgutter_git_executable.' --no-pager '.g:gitgutter_git_args if s:c_flag let cmd .= ' -c "diff.autorefreshindex=0"' let cmd .= ' -c "diff.noprefix=false"' let cmd .= ' -c "core.safecrlf=false"' endif - let cmd .= ' diff --no-ext-diff --no-color -U0 '.g:gitgutter_diff_args.' -- '.index_file.' '.buff_file + let cmd .= ' diff --no-ext-diff --no-color -U0 '.g:gitgutter_diff_args.' -- '.from_file.' '.buff_file " Pipe git-diff output into grep. if !a:preserve_full_diff && !empty(g:gitgutter_grep) diff --git a/autoload/gitgutter/hunk.vim b/autoload/gitgutter/hunk.vim index d3e55bb..4da3bb9 100644 --- a/autoload/gitgutter/hunk.vim +++ b/autoload/gitgutter/hunk.vim @@ -151,7 +151,7 @@ function! s:hunk_op(op) if gitgutter#utility#is_active(bufnr) " Get a (synchronous) diff. let [async, g:gitgutter_async] = [g:gitgutter_async, 0] - let diff = gitgutter#diff#run_diff(bufnr, 1) + let diff = gitgutter#diff#run_diff(bufnr, 'index', 1) let g:gitgutter_async = async call gitgutter#hunk#set_hunks(bufnr, gitgutter#diff#parse_diff(diff))