Make configured_tree a caching global function

This implements the changes suggested in tpope/fugitive#415.
s:repo_configured_tree is now a global, s:configured_tree() that caches
the bidirectional relation between the worktree and the git_dir.
extract_git_dir() now uses that relation to check whether the
directories it scans are valid worktrees known by the repo at $GIT_DIR.
This commit is contained in:
John Whitley 2014-11-06 10:38:07 -08:00 committed by Tim Pope
parent 5699f4613c
commit d3b98d9886

View File

@ -145,6 +145,13 @@ function! fugitive#extract_git_dir(path) abort
if root ==# $GIT_WORK_TREE && fugitive#is_git_dir($GIT_DIR) if root ==# $GIT_WORK_TREE && fugitive#is_git_dir($GIT_DIR)
return $GIT_DIR return $GIT_DIR
endif endif
if fugitive#is_git_dir($GIT_DIR)
" Ensure that we've cached the worktree
call s:configured_tree($GIT_DIR)
if has_key(s:dir_for_worktree, root)
return s:dir_for_worktree[root]
endif
endif
let dir = s:sub(root, '[\/]$', '') . '/.git' let dir = s:sub(root, '[\/]$', '') . '/.git'
let type = getftype(dir) let type = getftype(dir)
if type ==# 'dir' && fugitive#is_git_dir(dir) if type ==# 'dir' && fugitive#is_git_dir(dir)
@ -211,6 +218,8 @@ augroup END
let s:repo_prototype = {} let s:repo_prototype = {}
let s:repos = {} let s:repos = {}
let s:worktree_for_dir = {}
let s:dir_for_worktree = {}
function! s:repo(...) abort function! s:repo(...) abort
let dir = a:0 ? a:1 : (exists('b:git_dir') && b:git_dir !=# '' ? b:git_dir : fugitive#extract_git_dir(expand('%:p'))) let dir = a:0 ? a:1 : (exists('b:git_dir') && b:git_dir !=# '' ? b:git_dir : fugitive#extract_git_dir(expand('%:p')))
@ -234,21 +243,23 @@ function! s:repo_dir(...) dict abort
return join([self.git_dir]+a:000,'/') return join([self.git_dir]+a:000,'/')
endfunction endfunction
function! s:repo_configured_tree() dict abort function! s:configured_tree(git_dir) abort
if !has_key(self,'_tree') if !has_key(s:worktree_for_dir, a:git_dir)
let self._tree = '' let s:worktree_for_dir[a:git_dir] = ''
if filereadable(self.dir('config')) let config_file = a:git_dir . '/config'
let config = readfile(self.dir('config'),'',10) if filereadable(config_file)
let config = readfile(config_file,'',10)
call filter(config,'v:val =~# "^\\s*worktree *="') call filter(config,'v:val =~# "^\\s*worktree *="')
if len(config) == 1 if len(config) == 1
let self._tree = matchstr(config[0], '= *\zs.*') let s:worktree_for_dir[a:git_dir] = matchstr(config[0], '= *\zs.*')
let s:dir_for_worktree[s:worktree_for_dir[a:git_dir]] = a:git_dir
endif endif
endif endif
endif endif
if self._tree =~# '^\.' if s:worktree_for_dir[a:git_dir] =~# '^\.'
return simplify(self.dir(self._tree)) return simplify(a:git_dir . '/' . s:worktree_for_dir[a:git_dir])
else else
return self._tree return s:worktree_for_dir[a:git_dir]
endif endif
endfunction endfunction
@ -256,7 +267,7 @@ function! s:repo_tree(...) dict abort
if self.dir() =~# '/\.git$' if self.dir() =~# '/\.git$'
let dir = self.dir()[0:-6] let dir = self.dir()[0:-6]
else else
let dir = self.configured_tree() let dir = s:configured_tree(self.git_dir)
endif endif
if dir ==# '' if dir ==# ''
call s:throw('no work tree') call s:throw('no work tree')
@ -269,7 +280,7 @@ function! s:repo_bare() dict abort
if self.dir() =~# '/\.git$' if self.dir() =~# '/\.git$'
return 0 return 0
else else
return self.configured_tree() ==# '' return s:configured_tree(self.git_dir) ==# ''
endif endif
endfunction endfunction
@ -334,7 +345,7 @@ function! s:repo_head(...) dict abort
return branch return branch
endfunction endfunction
call s:add_methods('repo',['dir','configured_tree','tree','bare','translate','head']) call s:add_methods('repo',['dir','tree','bare','translate','head'])
function! s:repo_git_command(...) dict abort function! s:repo_git_command(...) dict abort
let git = g:fugitive_git_executable . ' --git-dir='.s:shellesc(self.git_dir) let git = g:fugitive_git_executable . ' --git-dir='.s:shellesc(self.git_dir)