From 885538efcdaad9ed8a293037abffbd4e9c52b08d Mon Sep 17 00:00:00 2001 From: Andy Stewart Date: Fri, 2 Jun 2023 16:01:51 +0100 Subject: [PATCH] Stage entire file if clean/smudge filter applies MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If a file is subject to a clean/smudge filter, it is impossible to stage an individual hunk. Therefore if the user tries to stage a hunk, ask whether they want to stage the entire instead. Determining whether a clean/smudge filter applies is done with: git check-attr filter -- path/to/file – and looking for "unspecified" (not to be) in the output. The result is cached so that for a file which is not filtered (the common case), staging multiple hunks only incurs the cost of the external call once. See #796. --- autoload/gitgutter/hunk.vim | 41 ++++++++++++++++++++++++++++++++----- 1 file changed, 36 insertions(+), 5 deletions(-) diff --git a/autoload/gitgutter/hunk.vim b/autoload/gitgutter/hunk.vim index 8f939f4..a590f57 100644 --- a/autoload/gitgutter/hunk.vim +++ b/autoload/gitgutter/hunk.vim @@ -294,11 +294,28 @@ endfunction function! s:stage(hunk_diff) let bufnr = bufnr('') - let diff = s:adjust_header(bufnr, a:hunk_diff) - " Apply patch to index. - call gitgutter#utility#system( - \ gitgutter#utility#cd_cmd(bufnr, g:gitgutter_git_executable.' '.g:gitgutter_git_args.' apply --cached --unidiff-zero - '), - \ diff) + + if s:clean_smudge_filter_applies(bufnr) + let choice = input('File uses clean/smudge filter. Stage entire file (y/n)? ') + normal! : + if choice =~ 'y' + let path = gitgutter#utility#repo_path(bufnr, 1) + " Add file to index. + call gitgutter#utility#system( + \ gitgutter#utility#cd_cmd(bufnr, g:gitgutter_git_executable.' '.g:gitgutter_git_args.' add '.path) + \ ) + else + return + endif + + else + let diff = s:adjust_header(bufnr, a:hunk_diff) + " Apply patch to index. + call gitgutter#utility#system( + \ gitgutter#utility#cd_cmd(bufnr, g:gitgutter_git_executable.' '.g:gitgutter_git_args.' apply --cached --unidiff-zero - '), + \ diff) + endif + if v:shell_error call gitgutter#utility#warn('Patch does not apply') else @@ -637,3 +654,17 @@ function gitgutter#hunk#is_preview_window_open() endif return 0 endfunction + + +function! s:clean_smudge_filter_applies(bufnr) + let filtered = gitgutter#utility#getbufvar(a:bufnr, 'filter', -1) + if filtered == -1 + let path = gitgutter#utility#repo_path(a:bufnr, 1) + let out = gitgutter#utility#system( + \ gitgutter#utility#cd_cmd(a:bufnr, g:gitgutter_git_executable.' '.g:gitgutter_git_args.' check-attr filter -- '.path) + \ ) + let filtered = out !~ 'unspecified' + call gitgutter#utility#setbufvar(a:bufnr, 'filter', filtered) + endif + return filtered +endfunction