" Location: autoload/fugitive.vim
" Maintainer: Tim Pope
if exists('g:autoloaded_fugitive')
finish
endif
let g:autoloaded_fugitive = 1
if !exists('g:fugitive_git_executable')
let g:fugitive_git_executable = 'git'
endif
" Section: Utility
function! s:function(name) abort
return function(substitute(a:name,'^s:',matchstr(expand(''), '\d\+_'),''))
endfunction
function! s:sub(str,pat,rep) abort
return substitute(a:str,'\v\C'.a:pat,a:rep,'')
endfunction
function! s:gsub(str,pat,rep) abort
return substitute(a:str,'\v\C'.a:pat,a:rep,'g')
endfunction
function! s:Uniq(list) abort
let i = 0
let seen = {}
while i < len(a:list)
let str = string(a:list[i])
if has_key(seen, str)
call remove(a:list, i)
else
let seen[str] = 1
let i += 1
endif
endwhile
return a:list
endfunction
function! s:winshell() abort
return &shell =~? 'cmd' || exists('+shellslash') && !&shellslash
endfunction
function! s:shellesc(arg) abort
if a:arg =~ '^[A-Za-z0-9_/.-]\+$'
return a:arg
elseif s:winshell()
return '"'.s:gsub(s:gsub(a:arg, '"', '""'), '\%', '"%"').'"'
else
return shellescape(a:arg)
endif
endfunction
function! s:fnameescape(file) abort
if exists('*fnameescape')
return fnameescape(a:file)
else
return escape(a:file," \t\n*?[{`$\\%#'\"|!<")
endif
endfunction
function! s:tempname() abort
let temp = resolve(tempname())
if has('win32')
let temp = fnamemodify(fnamemodify(temp, ':h'), ':p').fnamemodify(temp, ':t')
endif
return temp
endfunction
function! s:throw(string) abort
let v:errmsg = 'fugitive: '.a:string
throw v:errmsg
endfunction
function! s:warn(str) abort
echohl WarningMsg
echomsg a:str
echohl None
let v:warningmsg = a:str
endfunction
function! s:Slash(path) abort
if s:winshell()
return tr(a:path, '\', '/')
else
return a:path
endif
endfunction
function! s:PlatformSlash(path) abort
if exists('+shellslash') && !&shellslash
return tr(a:path, '/', '\')
else
return a:path
endif
endfunction
function! s:cpath(path, ...) abort
if exists('+fileignorecase') && &fileignorecase
let path = s:PlatformSlash(tolower(a:path))
else
let path = s:PlatformSlash(a:path)
endif
return a:0 ? path ==# s:cpath(a:1) : path
endfunction
let s:executables = {}
function! s:executable(binary) abort
if !has_key(s:executables, a:binary)
let s:executables[a:binary] = executable(a:binary)
endif
return s:executables[a:binary]
endfunction
function! s:UserCommand() abort
return get(g:, 'fugitive_git_command', g:fugitive_git_executable)
endfunction
function! s:System(cmd) abort
try
return system(a:cmd)
catch /^Vim\%((\a\+)\)\=:E484:/
let opts = ['shell', 'shellcmdflag', 'shellredir', 'shellquote', 'shellxquote', 'shellxescape', 'shellslash']
call filter(opts, 'exists("+".v:val) && !empty(eval("&".v:val))')
call map(opts, 'v:val."=".eval("&".v:val)')
call s:throw('failed to run `' . a:cmd . '` with ' . join(opts, ' '))
endtry
endfunction
function! s:Prepare(dir, ...) abort
let args = ['--git-dir=' . a:dir] + (a:000)
return g:fugitive_git_executable . ' ' . join(map(args, 's:shellesc(v:val)'))
endfunction
let s:git_versions = {}
function! fugitive#GitVersion(...) abort
if !has_key(s:git_versions, g:fugitive_git_executable)
let s:git_versions[g:fugitive_git_executable] = matchstr(system(g:fugitive_git_executable.' --version'), "\\S\\+\\ze\n")
endif
return s:git_versions[g:fugitive_git_executable]
endfunction
let s:commondirs = {}
function! fugitive#CommonDir(dir) abort
if empty(a:dir)
return ''
endif
if !has_key(s:commondirs, a:dir)
if getfsize(a:dir . '/HEAD') < 10
let s:commondirs[a:dir] = ''
elseif filereadable(a:dir . '/commondir')
let dir = get(readfile(a:dir . '/commondir', 1), 0, '')
if dir =~# '^/\|^\a:/'
let s:commondirs[a:dir] = dir
else
let s:commondirs[a:dir] = simplify(a:dir . '/' . dir)
endif
else
let s:commondirs[a:dir] = a:dir
endif
endif
return s:commondirs[a:dir]
endfunction
function! s:Tree(...) abort
return FugitiveTreeForGitDir(a:0 ? a:1 : get(b:, 'git_dir', ''))
endfunction
function! s:TreeChomp(...) abort
let args = copy(type(a:1) == type([]) ? a:1 : a:000)
let dir = a:0 > 1 && type(a:1) == type([]) ? a:2 : b:git_dir
let tree = s:Tree(dir)
let pre = ''
if empty(tree)
let args = ['--git-dir=' . dir] + args
elseif s:cpath(tree) !=# s:cpath(getcwd())
if fugitive#GitVersion() =~# '^[01]\.'
let pre = 'cd ' . s:shellesc(tree) . (s:winshell() ? ' & ' : '; ')
else
let args = ['-C', tree] + args
endif
endif
return s:sub(s:System(pre . g:fugitive_git_executable . ' ' .
\ join(map(args, 's:shellesc(v:val)'))), '\n$', '')
endfunction
function! fugitive#Prepare(cmd, ...) abort
let dir = a:0 ? a:1 : get(b:, 'git_dir', '')
let tree = s:Tree(dir)
let args = type(a:cmd) == type([]) ? join(map(copy(a:cmd), 's:shellesc(v:val)')) : a:cmd
let pre = ''
if empty(tree)
let args = s:shellesc('--git-dir=' . dir) . ' ' . args
elseif fugitive#GitVersion() =~# '^[01]\.'
let pre = 'cd ' . s:shellesc(tree) . (s:winshell() ? ' & ' : '; ')
else
let args = '-C ' . s:shellesc(tree) . ' ' . args
endif
return pre . g:fugitive_git_executable . ' ' . args
endfunction
function! fugitive#RevParse(rev, ...) abort
let hash = system(s:Prepare(a:0 ? a:1 : b:git_dir, 'rev-parse', '--verify', a:rev))[0:-2]
if !v:shell_error && hash =~# '^\x\{40\}$'
return hash
endif
call s:throw('rev-parse '.a:rev.': '.hash)
endfunction
function! fugitive#Config(name, ...) abort
let cmd = s:Prepare(a:0 ? a:1 : get(b:, 'git_dir', ''), 'config', '--get', a:name)
let out = matchstr(system(cmd), "[^\r\n]*")
return v:shell_error ? '' : out
endfunction
function! s:Remote(dir) abort
let head = FugitiveHead(0, a:dir)
let remote = len(head) ? fugitive#Config('branch.' . head . '.remote') : ''
let i = 10
while remote ==# '.' && i > 0
let head = matchstr(fugitive#Config('branch.' . head . '.merge'), 'refs/heads/\zs.*')
let remote = len(head) ? fugitive#Config('branch.' . head . '.remote') : ''
let i -= 1
endwhile
return remote =~# '^\.\=$' ? 'origin' : remote
endfunction
function! fugitive#RemoteUrl(...) abort
let dir = a:0 > 1 ? a:2 : get(b:, 'git_dir', '')
let remote = !a:0 || a:1 =~# '^\.\=$' ? s:Remote(dir) : a:1
if fugitive#GitVersion() =~# '^[01]\.\|^2\.[0-6]\.'
return fugitive#Config('remote.' . remote . '.url')
endif
let cmd = s:Prepare(dir, 'remote', 'get-url', remote)
let out = substitute(system(cmd), "\n$", '', '')
return v:shell_error ? '' : out
endfunction
function! s:recall() abort
let rev = s:sub(fugitive#buffer().rev(), '^/', '')
if rev ==# ':'
return matchstr(getline('.'),'^.\=\t\%([[:alpha:] ]\+: *\)\=\zs.\{-\}\ze\%( ([^()[:digit:]]\+)\)\=$\|^\d\{6} \x\{40\} \d\t\zs.*')
elseif fugitive#buffer().type('tree')
let file = matchstr(getline('.'), '\t\zs.*')
if empty(file) && line('.') > 2
let file = s:sub(getline('.'), '/$', '')
endif
if !empty(file) && rev !~# ':$'
return rev . '/' . file
else
return rev . file
endif
endif
return rev
endfunction
function! s:map(mode, lhs, rhs, ...) abort
let flags = (a:0 ? a:1 : '') . (a:rhs =~# '' ? '' : '