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)
return $GIT_DIR
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 type = getftype(dir)
if type ==# 'dir' && fugitive#is_git_dir(dir)
@ -211,6 +218,8 @@ augroup END
let s:repo_prototype = {}
let s:repos = {}
let s:worktree_for_dir = {}
let s:dir_for_worktree = {}
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')))
@ -234,21 +243,23 @@ function! s:repo_dir(...) dict abort
return join([self.git_dir]+a:000,'/')
endfunction
function! s:repo_configured_tree() dict abort
if !has_key(self,'_tree')
let self._tree = ''
if filereadable(self.dir('config'))
let config = readfile(self.dir('config'),'',10)
function! s:configured_tree(git_dir) abort
if !has_key(s:worktree_for_dir, a:git_dir)
let s:worktree_for_dir[a:git_dir] = ''
let config_file = a:git_dir . '/config'
if filereadable(config_file)
let config = readfile(config_file,'',10)
call filter(config,'v:val =~# "^\\s*worktree *="')
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
if self._tree =~# '^\.'
return simplify(self.dir(self._tree))
if s:worktree_for_dir[a:git_dir] =~# '^\.'
return simplify(a:git_dir . '/' . s:worktree_for_dir[a:git_dir])
else
return self._tree
return s:worktree_for_dir[a:git_dir]
endif
endfunction
@ -256,7 +267,7 @@ function! s:repo_tree(...) dict abort
if self.dir() =~# '/\.git$'
let dir = self.dir()[0:-6]
else
let dir = self.configured_tree()
let dir = s:configured_tree(self.git_dir)
endif
if dir ==# ''
call s:throw('no work tree')
@ -269,7 +280,7 @@ function! s:repo_bare() dict abort
if self.dir() =~# '/\.git$'
return 0
else
return self.configured_tree() ==# ''
return s:configured_tree(self.git_dir) ==# ''
endif
endfunction
@ -334,7 +345,7 @@ function! s:repo_head(...) dict abort
return branch
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
let git = g:fugitive_git_executable . ' --git-dir='.s:shellesc(self.git_dir)