Don't assume b:git_dir is an actual directory

This is a quick first pass.  There may be others hiding.

References https://github.com/tpope/vim-fugitive/issues/776
This commit is contained in:
Tim Pope
2019-06-02 16:19:09 -04:00
parent 79f3be9f17
commit 078ffa6197

View File

@@ -323,10 +323,10 @@ endfunction
function! fugitive#Head(...) abort function! fugitive#Head(...) abort
let dir = a:0 > 1 ? a:2 : s:Dir() let dir = a:0 > 1 ? a:2 : s:Dir()
if empty(dir) || !filereadable(dir . '/HEAD') if empty(dir) || !filereadable(fugitive#Find('.git/HEAD', dir))
return '' return ''
endif endif
let head = readfile(dir . '/HEAD')[0] let head = readfile(fugitive#Find('.git/HEAD', dir))[0]
if head =~# '^ref: ' if head =~# '^ref: '
return substitute(head, '\C^ref: \%(refs/\%(heads/\|remotes/\|tags/\)\=\)\=', '', '') return substitute(head, '\C^ref: \%(refs/\%(heads/\|remotes/\|tags/\)\=\)\=', '', '')
elseif head =~# '^\x\{40\}$' elseif head =~# '^\x\{40\}$'
@@ -561,6 +561,7 @@ function! s:Owner(path, ...) abort
if empty(dir) if empty(dir)
return '' return ''
endif endif
let actualdir = fugitive#Find('.git/', dir)
let [pdir, commit, file] = s:DirCommitFile(a:path) let [pdir, commit, file] = s:DirCommitFile(a:path)
if s:cpath(dir, pdir) if s:cpath(dir, pdir)
if commit =~# '^\x\{40\}$' if commit =~# '^\x\{40\}$'
@@ -568,9 +569,9 @@ function! s:Owner(path, ...) abort
elseif commit ==# '2' elseif commit ==# '2'
return 'HEAD^{}' return 'HEAD^{}'
endif endif
if filereadable(dir . '/MERGE_HEAD') if filereadable(actualdir . 'MERGE_HEAD')
let merge_head = 'MERGE_HEAD' let merge_head = 'MERGE_HEAD'
elseif filereadable(dir . '/REBASE_HEAD') elseif filereadable(actualdir . 'REBASE_HEAD')
let merge_head = 'REBASE_HEAD' let merge_head = 'REBASE_HEAD'
else else
return '' return ''
@@ -582,8 +583,8 @@ function! s:Owner(path, ...) abort
endif endif
endif endif
let path = fnamemodify(a:path, ':p') let path = fnamemodify(a:path, ':p')
if s:cpath(dir . '/', path[0 : len(dir)]) && a:path =~# 'HEAD$' if s:cpath(actualdir, strpart(path, 0, len(actualdir))) && a:path =~# 'HEAD$'
return strpart(path, len(dir) + 1) return strpart(path, len(actualdir))
endif endif
let refs = fugitive#CommonDir(dir) . '/refs' let refs = fugitive#CommonDir(dir) . '/refs'
if s:cpath(refs . '/', path[0 : len(refs)]) && path !~# '[\/]$' if s:cpath(refs . '/', path[0 : len(refs)]) && path !~# '[\/]$'
@@ -697,7 +698,7 @@ function! fugitive#Find(object, ...) abort
let f = base . f[3:-1] let f = base . f[3:-1]
elseif cdir !=# dir && ( elseif cdir !=# dir && (
\ f =~# '^/\%(config\|hooks\|info\|logs/refs\|objects\|refs\|worktrees\)\%(/\|$\)' || \ f =~# '^/\%(config\|hooks\|info\|logs/refs\|objects\|refs\|worktrees\)\%(/\|$\)' ||
\ f !~# '^/logs$\|/\w*HEAD$' && getftime(dir . f) < 0 && getftime(cdir . f) >= 0) \ f !~# '^/\%(index$\|index\.lock$\|\w*MSG$\|\w*HEAD$\|logs/\w*HEAD$\|logs$\|rebase-\w\+\)\%(/\|$\)' && getftime(dir . f) < 0 && getftime(cdir . f) >= 0)
let f = simplify(cdir . f) let f = simplify(cdir . f)
else else
let f = simplify(dir . f) let f = simplify(dir . f)
@@ -728,7 +729,7 @@ function! fugitive#Find(object, ...) abort
if $GIT_INDEX_FILE =~# '/[^/]*index[^/]*\.lock$' && s:cpath(fnamemodify($GIT_INDEX_FILE,':p')[0:strlen(dir)]) ==# s:cpath(dir . '/') && filereadable($GIT_INDEX_FILE) if $GIT_INDEX_FILE =~# '/[^/]*index[^/]*\.lock$' && s:cpath(fnamemodify($GIT_INDEX_FILE,':p')[0:strlen(dir)]) ==# s:cpath(dir . '/') && filereadable($GIT_INDEX_FILE)
let f = fnamemodify($GIT_INDEX_FILE, ':p') let f = fnamemodify($GIT_INDEX_FILE, ':p')
else else
let f = dir . '/index' let f = fugitive#Find('.git/index', dir)
endif endif
elseif rev =~# '^:(\%(top\|top,literal\|literal,top\|literal\))' elseif rev =~# '^:(\%(top\|top,literal\|literal,top\|literal\))'
let f = base . '/' . matchstr(rev, ')\zs.*') let f = base . '/' . matchstr(rev, ')\zs.*')
@@ -889,7 +890,7 @@ let s:indexes = {}
function! s:TreeInfo(dir, commit) abort function! s:TreeInfo(dir, commit) abort
if a:commit =~# '^:\=[0-3]$' if a:commit =~# '^:\=[0-3]$'
let index = get(s:indexes, a:dir, []) let index = get(s:indexes, a:dir, [])
let newftime = getftime(a:dir . '/index') let newftime = getftime(fugitive#Find('.git/index', a:dir))
if get(index, 0, -1) < newftime if get(index, 0, -1) < newftime
let out = system(fugitive#Prepare(a:dir, 'ls-files', '--stage', '--')) let out = system(fugitive#Prepare(a:dir, 'ls-files', '--stage', '--'))
let s:indexes[a:dir] = [newftime, {'0': {}, '1': {}, '2': {}, '3': {}}] let s:indexes[a:dir] = [newftime, {'0': {}, '1': {}, '2': {}, '3': {}}]
@@ -998,7 +999,7 @@ endfunction
function! fugitive#filewritable(url) abort function! fugitive#filewritable(url) abort
let [dir, commit, file] = s:DirCommitFile(a:url) let [dir, commit, file] = s:DirCommitFile(a:url)
if commit !~# '^\d$' || !filewritable(dir . '/index') if commit !~# '^\d$' || !filewritable(fugitive#Find('.git/index', dir))
return 0 return 0
endif endif
return s:PathInfo(a:url)[2] ==# 'blob' ? 1 : 2 return s:PathInfo(a:url)[2] ==# 'blob' ? 1 : 2
@@ -1134,7 +1135,7 @@ function! fugitive#glob(url, ...) abort
let pattern = '^' . substitute(glob, '/\=\*\*/\=\|/\=\*\|[.?\$]\|^^', '\=get(s:globsubs, submatch(0), "\\" . submatch(0))', 'g')[1:-1] . '$' let pattern = '^' . substitute(glob, '/\=\*\*/\=\|/\=\*\|[.?\$]\|^^', '\=get(s:globsubs, submatch(0), "\\" . submatch(0))', 'g')[1:-1] . '$'
let results = [] let results = []
for dir in dirglob =~# '[*?]' ? split(glob(dirglob), "\n") : [dirglob] for dir in dirglob =~# '[*?]' ? split(glob(dirglob), "\n") : [dirglob]
if empty(dir) || !get(g:, 'fugitive_file_api', 1) || !filereadable(dir . '/HEAD') if empty(dir) || !get(g:, 'fugitive_file_api', 1) || !filereadable(fugitive#Find('.git/HEAD', dir))
continue continue
endif endif
let files = items(s:TreeInfo(dir, commit)[0]) let files = items(s:TreeInfo(dir, commit)[0])
@@ -1405,7 +1406,7 @@ function! fugitive#BufReadStatus() abort
silent doautocmd BufReadPre silent doautocmd BufReadPre
let cmd = [fnamemodify(amatch, ':h')] let cmd = [fnamemodify(amatch, ':h')]
setlocal noro ma nomodeline buftype=nowrite setlocal noro ma nomodeline buftype=nowrite
if s:cpath(fnamemodify($GIT_INDEX_FILE !=# '' ? $GIT_INDEX_FILE : s:Dir() . '/index', ':p')) !=# s:cpath(amatch) if s:cpath(fnamemodify($GIT_INDEX_FILE !=# '' ? $GIT_INDEX_FILE : fugitive#Find('.git/index'), ':p')) !=# s:cpath(amatch)
let cmd += ['-c', 'GIT_INDEX_FILE=' . amatch] let cmd += ['-c', 'GIT_INDEX_FILE=' . amatch]
endif endif
let cmd += ['status', '--porcelain', '-bz'] let cmd += ['status', '--porcelain', '-bz']
@@ -1688,7 +1689,7 @@ function! fugitive#BufReadCmd(...) abort
let error = b:fugitive_type let error = b:fugitive_type
unlet b:fugitive_type unlet b:fugitive_type
if rev =~# '^:\d:' if rev =~# '^:\d:'
let &l:readonly = !filewritable(dir . '/index') let &l:readonly = !filewritable(fugitive#Find('.git/index', dir))
return 'silent doautocmd BufNewFile' return 'silent doautocmd BufNewFile'
else else
setlocal readonly nomodifiable setlocal readonly nomodifiable
@@ -1758,7 +1759,7 @@ function! fugitive#BufReadCmd(...) abort
keepjumps call setpos('.',pos) keepjumps call setpos('.',pos)
setlocal nomodified noswapfile setlocal nomodified noswapfile
let modifiable = rev =~# '^:.:' && b:fugitive_type !=# 'tree' let modifiable = rev =~# '^:.:' && b:fugitive_type !=# 'tree'
let &l:readonly = !modifiable || !filewritable(dir . '/index') let &l:readonly = !modifiable || !filewritable(fugitive#Find('.git/index', dir))
if &bufhidden ==# '' if &bufhidden ==# ''
setlocal bufhidden=delete setlocal bufhidden=delete
endif endif
@@ -2652,7 +2653,7 @@ function! s:CommitCommand(line1, line2, range, count, bang, mods, reg, arg, args
let mods = s:gsub(a:mods ==# '<mods>' ? '' : a:mods, '<tab>', '-tab') let mods = s:gsub(a:mods ==# '<mods>' ? '' : a:mods, '<tab>', '-tab')
let dir = a:0 ? a:1 : s:Dir() let dir = a:0 ? a:1 : s:Dir()
let tree = s:Tree(dir) let tree = s:Tree(dir)
let msgfile = dir . '/COMMIT_EDITMSG' let msgfile = fugitive#Find('.git/COMMIT_EDITMSG', dir)
let outfile = tempname() let outfile = tempname()
let errorfile = tempname() let errorfile = tempname()
try try
@@ -2836,7 +2837,7 @@ let s:rebase_abbrevs = {
\ } \ }
function! s:RebaseEdit(cmd, dir) abort function! s:RebaseEdit(cmd, dir) abort
let rebase_todo = s:fnameescape(a:dir . '/rebase-merge/git-rebase-todo') let rebase_todo = s:fnameescape(fugitive#Find('.git/rebase-merge/git-rebase-todo', a:dir))
if filereadable(rebase_todo) if filereadable(rebase_todo)
let new = readfile(rebase_todo) let new = readfile(rebase_todo)
@@ -2877,21 +2878,21 @@ function! s:Merge(cmd, bang, mods, args, ...) abort
return '' return ''
endif endif
return s:RebaseEdit(mods . 'split', dir) return s:RebaseEdit(mods . 'split', dir)
elseif a:cmd =~# '^rebase' && ' '.a:args =~# ' --edit-todo' && filereadable(dir . '/rebase-merge/git-rebase-todo') elseif a:cmd =~# '^rebase' && ' '.a:args =~# ' --edit-todo' && filereadable(fugitive#Find('.git/rebase-merge/git-rebase-todo', dir))
return s:RebaseEdit(mods . 'split', dir) return s:RebaseEdit(mods . 'split', dir)
elseif a:cmd =~# '^rebase' && ' '.a:args =~# ' --continue' && !a:0 elseif a:cmd =~# '^rebase' && ' '.a:args =~# ' --continue' && !a:0
let rdir = dir . '/rebase-merge' let rdir = fugitive#Find('.git/rebase-merge', dir)
call system(fugitive#Prepare(dir, 'diff-index', '--cached', '--quiet', 'HEAD', '--')) call system(fugitive#Prepare(dir, 'diff-index', '--cached', '--quiet', 'HEAD', '--'))
if v:shell_error && isdirectory(rdir) if v:shell_error && isdirectory(rdir)
if getfsize(rdir . '/amend') <= 0 if getfsize(rdir . '/amend') <= 0
return 'exe ' . string(mods . 'Gcommit -n -F ' . s:shellesc(dir . '/rebase-merge/message') . ' -e') . '|let b:fugitive_commit_rebase = 1' return 'exe ' . string(mods . 'Gcommit -n -F ' . s:shellesc(rdir .'/message') . ' -e') . '|let b:fugitive_commit_rebase = 1'
elseif readfile(rdir . '/amend')[0] ==# fugitive#Head(-1, dir) elseif readfile(rdir . '/amend')[0] ==# fugitive#Head(-1, dir)
return 'exe ' . string(mods . 'Gcommit --amend -n -F ' . s:shellesc(dir . '/rebase-merge/message') . ' -e') . '|let b:fugitive_commit_rebase = 1' return 'exe ' . string(mods . 'Gcommit --amend -n -F ' . s:shellesc(rdir . '/message') . ' -e') . '|let b:fugitive_commit_rebase = 1'
endif endif
endif endif
endif endif
let [mp, efm] = [&l:mp, &l:efm] let [mp, efm] = [&l:mp, &l:efm]
let had_merge_msg = filereadable(dir . '/MERGE_MSG') let had_merge_msg = filereadable(fugitive#Find('.git/MERGE_MSG', dir))
try try
let cdback = s:Cd(s:Tree(dir)) let cdback = s:Cd(s:Tree(dir))
let &l:errorformat = '' let &l:errorformat = ''
@@ -2916,7 +2917,7 @@ function! s:Merge(cmd, bang, mods, args, ...) abort
\ . "%+E\u51b2\u7a81 %.%#," \ . "%+E\u51b2\u7a81 %.%#,"
\ . 'U%\t%f' \ . 'U%\t%f'
if a:cmd =~# '^merge' && empty(a:args) && if a:cmd =~# '^merge' && empty(a:args) &&
\ (had_merge_msg || isdirectory(dir . '/rebase-apply') || \ (had_merge_msg || isdirectory(fugitive#Find('.git/rebase-apply', dir)) ||
\ !empty(s:TreeChomp(dir, 'diff-files', '--diff-filter=U'))) \ !empty(s:TreeChomp(dir, 'diff-files', '--diff-filter=U')))
let &l:makeprg = g:fugitive_git_executable.' diff-files --name-status --diff-filter=U' let &l:makeprg = g:fugitive_git_executable.' diff-files --name-status --diff-filter=U'
else else
@@ -2954,14 +2955,14 @@ function! s:Merge(cmd, bang, mods, args, ...) abort
call fugitive#ReloadStatus() call fugitive#ReloadStatus()
if empty(filter(getqflist(),'v:val.valid && v:val.type !=# "I"')) if empty(filter(getqflist(),'v:val.valid && v:val.type !=# "I"'))
if a:cmd =~# '^rebase' && if a:cmd =~# '^rebase' &&
\ filereadable(dir . '/rebase-merge/amend') && \ filereadable(fugitive#Find('.git/rebase-merge/amend', dir)) &&
\ filereadable(dir . '/rebase-merge/done') && \ filereadable(fugitive#Find('.git/rebase-merge/done', dir)) &&
\ get(readfile(dir . '/rebase-merge/done'), -1, '') =~# '^[^e]' \ get(readfile(fugitive#Find('.git/rebase-merge/done', dir)), -1, '') =~# '^[^e]'
cclose cclose
return 'exe ' . string(mods . 'Gcommit --amend -n -F ' . s:shellesc(dir . '/rebase-merge/message') . ' -e') . '|let b:fugitive_commit_rebase = 1' return 'exe ' . string(mods . 'Gcommit --amend -n -F ' . s:shellesc(fugitive#Find('.git/rebase-merge/message', dir)) . ' -e') . '|let b:fugitive_commit_rebase = 1'
elseif !had_merge_msg && filereadable(dir . '/MERGE_MSG') elseif !had_merge_msg && filereadable(fugitive#Find('.git/MERGE_MSG', dir))
cclose cclose
return mods . 'Gcommit --no-status -n -t '.s:shellesc(dir . '/MERGE_MSG') return mods . 'Gcommit --no-status -n -t '.s:shellesc(fugitive#Find('.git/MERGE_MSG', dir))
endif endif
endif endif
let qflist = getqflist() let qflist = getqflist()
@@ -4178,7 +4179,7 @@ function! s:BrowseCommand(line1, line2, range, count, bang, mods, reg, arg, args
endif endif
endif endif
if empty(commit) if empty(commit)
let commit = readfile(dir . '/HEAD', '', 1)[0] let commit = readfile(fugitive#Find('.git/HEAD', dir), '', 1)[0]
endif endif
let i = 0 let i = 0
while commit =~# '^ref: ' && i < 10 while commit =~# '^ref: ' && i < 10
@@ -4704,11 +4705,12 @@ function! fugitive#Init() abort
endif endif
let dir = s:Dir() let dir = s:Dir()
if stridx(&tags, escape(dir, ', ')) == -1 if stridx(&tags, escape(dir, ', ')) == -1
if filereadable(dir.'/tags') let actualdir = fugitive#Find('.git/', dir)
let &l:tags = escape(dir.'/tags', ', ').','.&tags if filereadable(actualdir . 'tags')
let &l:tags = escape(actualdir . 'tags', ', ').','.&tags
endif endif
if &filetype !=# '' && filereadable(dir.'/'.&filetype.'.tags') if &filetype !=# '' && filereadable(actualdir . &filetype . '.tags')
let &l:tags = escape(dir.'/'.&filetype.'.tags', ', ').','.&tags let &l:tags = escape(actualdir . &filetype . '.tags', ', ').','.&tags
endif endif
endif endif
try try