2010-02-14 14:16:30 -05:00
|
|
|
" fugitive.vim - A Git wrapper so awesome, it should be illegal
|
2011-08-06 16:55:57 -04:00
|
|
|
" Maintainer: Tim Pope <http://tpo.pe/>
|
2015-01-20 01:37:22 -05:00
|
|
|
" Version: 2.2
|
2010-02-15 14:03:22 -05:00
|
|
|
" GetLatestVimScripts: 2975 1 :AutoInstall: fugitive.vim
|
2009-10-10 19:47:14 -04:00
|
|
|
|
2010-02-15 14:03:04 -05:00
|
|
|
if exists('g:loaded_fugitive') || &cp
|
2009-10-10 19:47:14 -04:00
|
|
|
finish
|
|
|
|
endif
|
|
|
|
let g:loaded_fugitive = 1
|
|
|
|
|
|
|
|
if !exists('g:fugitive_git_executable')
|
|
|
|
let g:fugitive_git_executable = 'git'
|
|
|
|
endif
|
|
|
|
|
2014-06-21 08:48:11 -04:00
|
|
|
" Section: Utility
|
2009-10-10 19:47:14 -04:00
|
|
|
|
|
|
|
function! s:function(name) abort
|
|
|
|
return function(substitute(a:name,'^s:',matchstr(expand('<sfile>'), '<SNR>\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
|
|
|
|
|
2014-06-21 11:11:17 -04:00
|
|
|
function! s:winshell() abort
|
2014-06-22 13:30:41 -04:00
|
|
|
return &shell =~? 'cmd' || exists('+shellslash') && !&shellslash
|
2014-06-21 11:11:17 -04:00
|
|
|
endfunction
|
|
|
|
|
2009-10-10 19:47:14 -04:00
|
|
|
function! s:shellesc(arg) abort
|
|
|
|
if a:arg =~ '^[A-Za-z0-9_/.-]\+$'
|
|
|
|
return a:arg
|
2014-06-21 11:11:17 -04:00
|
|
|
elseif s:winshell()
|
2012-04-21 10:11:02 -04:00
|
|
|
return '"'.s:gsub(s:gsub(a:arg, '"', '""'), '\%', '"%"').'"'
|
2009-10-10 19:47:14 -04:00
|
|
|
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:throw(string) abort
|
|
|
|
let v:errmsg = 'fugitive: '.a:string
|
|
|
|
throw v:errmsg
|
|
|
|
endfunction
|
|
|
|
|
2014-03-27 17:22:35 -04:00
|
|
|
function! s:warn(str) abort
|
2010-01-09 19:12:45 -05:00
|
|
|
echohl WarningMsg
|
|
|
|
echomsg a:str
|
|
|
|
echohl None
|
|
|
|
let v:warningmsg = a:str
|
|
|
|
endfunction
|
|
|
|
|
2014-03-27 17:22:35 -04:00
|
|
|
function! s:shellslash(path) abort
|
2014-06-21 11:11:17 -04:00
|
|
|
if s:winshell()
|
2010-03-09 19:03:44 -05:00
|
|
|
return s:gsub(a:path,'\\','/')
|
|
|
|
else
|
|
|
|
return a:path
|
|
|
|
endif
|
|
|
|
endfunction
|
|
|
|
|
2013-10-24 00:15:40 -04:00
|
|
|
let s:git_versions = {}
|
|
|
|
|
|
|
|
function! fugitive#git_version(...) 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\\+\n")
|
|
|
|
endif
|
|
|
|
return s:git_versions[g:fugitive_git_executable]
|
|
|
|
endfunction
|
|
|
|
|
2014-03-27 17:22:35 -04:00
|
|
|
function! s:recall() abort
|
2012-04-07 15:42:09 -04:00
|
|
|
let rev = s:sub(s:buffer().rev(), '^/', '')
|
2011-08-09 15:15:05 -04:00
|
|
|
if rev ==# ':'
|
2012-07-28 11:54:52 -04:00
|
|
|
return matchstr(getline('.'),'^#\t\%([[:alpha:] ]\+: *\)\=\zs.\{-\}\ze\%( ([^()[:digit:]]\+)\)\=$\|^\d\{6} \x\{40\} \d\t\zs.*')
|
2013-03-12 02:15:40 -04:00
|
|
|
elseif s: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
|
2011-08-09 15:15:05 -04:00
|
|
|
endif
|
|
|
|
return rev
|
|
|
|
endfunction
|
|
|
|
|
2009-10-10 19:47:14 -04:00
|
|
|
function! s:add_methods(namespace, method_names) abort
|
|
|
|
for name in a:method_names
|
|
|
|
let s:{a:namespace}_prototype[name] = s:function('s:'.a:namespace.'_'.name)
|
|
|
|
endfor
|
|
|
|
endfunction
|
|
|
|
|
|
|
|
let s:commands = []
|
|
|
|
function! s:command(definition) abort
|
|
|
|
let s:commands += [a:definition]
|
|
|
|
endfunction
|
|
|
|
|
2014-03-27 17:22:35 -04:00
|
|
|
function! s:define_commands() abort
|
2009-10-10 19:47:14 -04:00
|
|
|
for command in s:commands
|
|
|
|
exe 'command! -buffer '.command
|
|
|
|
endfor
|
|
|
|
endfunction
|
|
|
|
|
2010-01-24 23:07:19 -05:00
|
|
|
augroup fugitive_utility
|
2009-10-10 19:47:14 -04:00
|
|
|
autocmd!
|
|
|
|
autocmd User Fugitive call s:define_commands()
|
|
|
|
augroup END
|
|
|
|
|
|
|
|
let s:abstract_prototype = {}
|
|
|
|
|
2014-06-21 08:48:11 -04:00
|
|
|
" Section: Initialization
|
2009-10-10 19:47:14 -04:00
|
|
|
|
2012-03-18 22:44:04 -04:00
|
|
|
function! fugitive#is_git_dir(path) abort
|
2012-06-04 15:16:48 -04:00
|
|
|
let path = s:sub(a:path, '[\/]$', '') . '/'
|
2012-03-18 22:44:04 -04:00
|
|
|
return isdirectory(path.'objects') && isdirectory(path.'refs') && getfsize(path.'HEAD') > 10
|
|
|
|
endfunction
|
|
|
|
|
|
|
|
function! fugitive#extract_git_dir(path) abort
|
2012-03-25 22:19:19 -04:00
|
|
|
if s:shellslash(a:path) =~# '^fugitive://.*//'
|
|
|
|
return matchstr(s:shellslash(a:path), '\C^fugitive://\zs.\{-\}\ze//')
|
2012-03-18 22:44:04 -04:00
|
|
|
endif
|
2012-07-15 13:03:09 -04:00
|
|
|
let root = s:shellslash(simplify(fnamemodify(a:path, ':p:s?[\/]$??')))
|
2012-03-18 22:44:04 -04:00
|
|
|
let previous = ""
|
|
|
|
while root !=# previous
|
2013-12-17 07:33:07 -05:00
|
|
|
if root =~# '\v^//%([^/]+/?)?$'
|
|
|
|
" This is for accessing network shares from Cygwin Vim. There won't be
|
|
|
|
" any git directory called //.git or //serverName/.git so let's avoid
|
|
|
|
" checking for them since such checks are extremely slow.
|
|
|
|
break
|
|
|
|
endif
|
2014-01-21 18:39:48 -05:00
|
|
|
if index(split($GIT_CEILING_DIRECTORIES, ':'), root) >= 0
|
|
|
|
break
|
|
|
|
endif
|
2014-03-02 21:21:48 -05:00
|
|
|
if root ==# $GIT_WORK_TREE && fugitive#is_git_dir($GIT_DIR)
|
|
|
|
return $GIT_DIR
|
|
|
|
endif
|
2014-11-06 13:38:07 -05:00
|
|
|
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
|
2012-03-18 22:44:04 -04:00
|
|
|
let dir = s:sub(root, '[\/]$', '') . '/.git'
|
|
|
|
let type = getftype(dir)
|
|
|
|
if type ==# 'dir' && fugitive#is_git_dir(dir)
|
|
|
|
return dir
|
|
|
|
elseif type ==# 'link' && fugitive#is_git_dir(dir)
|
|
|
|
return resolve(dir)
|
2012-03-20 08:10:46 -04:00
|
|
|
elseif type !=# '' && filereadable(dir)
|
2012-04-03 06:52:48 -04:00
|
|
|
let line = get(readfile(dir, '', 1), 0, '')
|
2012-05-15 21:50:13 -04:00
|
|
|
if line =~# '^gitdir: \.' && fugitive#is_git_dir(root.'/'.line[8:-1])
|
|
|
|
return simplify(root.'/'.line[8:-1])
|
|
|
|
elseif line =~# '^gitdir: ' && fugitive#is_git_dir(line[8:-1])
|
2012-03-14 22:02:20 -04:00
|
|
|
return line[8:-1]
|
|
|
|
endif
|
2012-03-18 22:44:04 -04:00
|
|
|
elseif fugitive#is_git_dir(root)
|
|
|
|
return root
|
2009-10-10 19:47:14 -04:00
|
|
|
endif
|
2012-03-18 22:44:04 -04:00
|
|
|
let previous = root
|
2012-04-10 22:49:31 -04:00
|
|
|
let root = fnamemodify(root, ':h')
|
2009-10-10 19:47:14 -04:00
|
|
|
endwhile
|
|
|
|
return ''
|
|
|
|
endfunction
|
|
|
|
|
2014-03-27 17:22:35 -04:00
|
|
|
function! fugitive#detect(path) abort
|
2011-08-06 17:05:46 -04:00
|
|
|
if exists('b:git_dir') && (b:git_dir ==# '' || b:git_dir =~# '/$')
|
2010-01-24 22:59:42 -05:00
|
|
|
unlet b:git_dir
|
|
|
|
endif
|
2009-10-10 19:47:14 -04:00
|
|
|
if !exists('b:git_dir')
|
2012-03-18 22:44:04 -04:00
|
|
|
let dir = fugitive#extract_git_dir(a:path)
|
2012-04-10 22:49:31 -04:00
|
|
|
if dir !=# ''
|
2009-10-10 19:47:14 -04:00
|
|
|
let b:git_dir = dir
|
|
|
|
endif
|
|
|
|
endif
|
|
|
|
if exists('b:git_dir')
|
2014-11-20 15:43:36 -05:00
|
|
|
if exists('#User#FugitiveBoot')
|
|
|
|
try
|
|
|
|
let [save_mls, &modelines] = [&mls, 0]
|
|
|
|
doautocmd User FugitiveBoot
|
|
|
|
finally
|
|
|
|
let &mls = save_mls
|
|
|
|
endtry
|
|
|
|
endif
|
2015-02-11 07:14:53 -05:00
|
|
|
if !exists('g:fugitive_no_maps')
|
|
|
|
cnoremap <buffer> <expr> <C-R><C-G> fnameescape(<SID>recall())
|
|
|
|
nnoremap <buffer> <silent> y<C-G> :call setreg(v:register, <SID>recall())<CR>
|
|
|
|
endif
|
2010-07-28 14:41:11 -04:00
|
|
|
let buffer = fugitive#buffer()
|
2009-12-13 19:49:35 -05:00
|
|
|
if expand('%:p') =~# '//'
|
2012-04-10 22:49:31 -04:00
|
|
|
call buffer.setvar('&path', s:sub(buffer.getvar('&path'), '^\.%(,|$)', ''))
|
2009-12-13 19:49:35 -05:00
|
|
|
endif
|
2014-07-06 00:20:19 -04:00
|
|
|
if stridx(buffer.getvar('&tags'), escape(b:git_dir, ', ')) == -1
|
|
|
|
if filereadable(b:git_dir.'/tags')
|
|
|
|
call buffer.setvar('&tags', escape(b:git_dir.'/tags', ', ').','.buffer.getvar('&tags'))
|
|
|
|
endif
|
|
|
|
if &filetype !=# '' && filereadable(b:git_dir.'/'.&filetype.'.tags')
|
2012-12-16 20:23:12 -05:00
|
|
|
call buffer.setvar('&tags', escape(b:git_dir.'/'.&filetype.'.tags', ', ').','.buffer.getvar('&tags'))
|
2011-02-07 15:02:25 -05:00
|
|
|
endif
|
2010-07-28 14:41:11 -04:00
|
|
|
endif
|
2014-11-20 15:43:36 -05:00
|
|
|
try
|
|
|
|
let [save_mls, &modelines] = [&mls, 0]
|
|
|
|
doautocmd User Fugitive
|
|
|
|
finally
|
|
|
|
let &mls = save_mls
|
|
|
|
endtry
|
2009-10-10 19:47:14 -04:00
|
|
|
endif
|
|
|
|
endfunction
|
|
|
|
|
|
|
|
augroup fugitive
|
|
|
|
autocmd!
|
2013-02-23 12:24:24 -05:00
|
|
|
autocmd BufNewFile,BufReadPost * call fugitive#detect(expand('<amatch>:p'))
|
|
|
|
autocmd FileType netrw call fugitive#detect(expand('%:p'))
|
|
|
|
autocmd User NERDTreeInit,NERDTreeNewRoot call fugitive#detect(b:NERDTreeRoot.path.str())
|
|
|
|
autocmd VimEnter * if expand('<amatch>')==''|call fugitive#detect(getcwd())|endif
|
2014-04-02 02:14:32 -04:00
|
|
|
autocmd CmdWinEnter * call fugitive#detect(expand('#:p'))
|
2011-10-04 03:10:04 -04:00
|
|
|
autocmd BufWinLeave * execute getwinvar(+bufwinnr(+expand('<abuf>')), 'fugitive_leave')
|
2009-10-10 19:47:14 -04:00
|
|
|
augroup END
|
|
|
|
|
2014-06-21 08:48:11 -04:00
|
|
|
" Section: Repository
|
2009-10-10 19:47:14 -04:00
|
|
|
|
|
|
|
let s:repo_prototype = {}
|
|
|
|
let s:repos = {}
|
2014-11-06 13:38:07 -05:00
|
|
|
let s:worktree_for_dir = {}
|
|
|
|
let s:dir_for_worktree = {}
|
2009-10-10 19:47:14 -04:00
|
|
|
|
|
|
|
function! s:repo(...) abort
|
2012-03-18 22:44:04 -04:00
|
|
|
let dir = a:0 ? a:1 : (exists('b:git_dir') && b:git_dir !=# '' ? b:git_dir : fugitive#extract_git_dir(expand('%:p')))
|
2009-11-10 21:17:21 -05:00
|
|
|
if dir !=# ''
|
2012-04-10 22:49:31 -04:00
|
|
|
if has_key(s:repos, dir)
|
|
|
|
let repo = get(s:repos, dir)
|
2009-10-10 19:47:14 -04:00
|
|
|
else
|
|
|
|
let repo = {'git_dir': dir}
|
|
|
|
let s:repos[dir] = repo
|
|
|
|
endif
|
2012-04-10 22:49:31 -04:00
|
|
|
return extend(extend(repo, s:repo_prototype, 'keep'), s:abstract_prototype, 'keep')
|
2009-10-10 19:47:14 -04:00
|
|
|
endif
|
2009-11-10 21:17:21 -05:00
|
|
|
call s:throw('not a git repository: '.expand('%:p'))
|
2009-10-10 19:47:14 -04:00
|
|
|
endfunction
|
|
|
|
|
2014-03-27 17:22:35 -04:00
|
|
|
function! fugitive#repo(...) abort
|
2011-10-04 20:25:32 -04:00
|
|
|
return call('s:repo', a:000)
|
|
|
|
endfunction
|
|
|
|
|
2009-10-10 19:47:14 -04:00
|
|
|
function! s:repo_dir(...) dict abort
|
|
|
|
return join([self.git_dir]+a:000,'/')
|
|
|
|
endfunction
|
|
|
|
|
2014-11-06 13:38:07 -05:00
|
|
|
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)
|
2012-03-18 22:22:28 -04:00
|
|
|
call filter(config,'v:val =~# "^\\s*worktree *="')
|
|
|
|
if len(config) == 1
|
2014-11-06 13:38:07 -05:00
|
|
|
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
|
2012-03-18 22:22:28 -04:00
|
|
|
endif
|
2012-03-14 22:02:20 -04:00
|
|
|
endif
|
2009-10-10 19:47:14 -04:00
|
|
|
endif
|
2014-11-06 13:38:07 -05:00
|
|
|
if s:worktree_for_dir[a:git_dir] =~# '^\.'
|
|
|
|
return simplify(a:git_dir . '/' . s:worktree_for_dir[a:git_dir])
|
2012-05-17 21:42:06 -04:00
|
|
|
else
|
2014-11-06 13:38:07 -05:00
|
|
|
return s:worktree_for_dir[a:git_dir]
|
2012-05-17 21:42:06 -04:00
|
|
|
endif
|
2012-03-18 22:09:46 -04:00
|
|
|
endfunction
|
|
|
|
|
|
|
|
function! s:repo_tree(...) dict abort
|
|
|
|
if self.dir() =~# '/\.git$'
|
|
|
|
let dir = self.dir()[0:-6]
|
|
|
|
else
|
2014-11-06 13:38:07 -05:00
|
|
|
let dir = s:configured_tree(self.git_dir)
|
2012-03-18 22:09:46 -04:00
|
|
|
endif
|
|
|
|
if dir ==# ''
|
|
|
|
call s:throw('no work tree')
|
|
|
|
else
|
|
|
|
return join([dir]+a:000,'/')
|
|
|
|
endif
|
2009-10-10 19:47:14 -04:00
|
|
|
endfunction
|
|
|
|
|
|
|
|
function! s:repo_bare() dict abort
|
2012-03-14 22:02:20 -04:00
|
|
|
if self.dir() =~# '/\.git$'
|
|
|
|
return 0
|
|
|
|
else
|
2014-11-06 13:38:07 -05:00
|
|
|
return s:configured_tree(self.git_dir) ==# ''
|
2013-07-21 21:52:08 -04:00
|
|
|
endif
|
2009-10-10 19:47:14 -04:00
|
|
|
endfunction
|
|
|
|
|
|
|
|
function! s:repo_translate(spec) dict abort
|
|
|
|
if a:spec ==# '.' || a:spec ==# '/.'
|
|
|
|
return self.bare() ? self.dir() : self.tree()
|
2012-03-27 13:33:04 -04:00
|
|
|
elseif a:spec =~# '^/\=\.git$' && self.bare()
|
|
|
|
return self.dir()
|
|
|
|
elseif a:spec =~# '^/\=\.git/'
|
|
|
|
return self.dir(s:sub(a:spec, '^/=\.git/', ''))
|
2009-10-10 19:47:14 -04:00
|
|
|
elseif a:spec =~# '^/'
|
2012-03-27 13:33:04 -04:00
|
|
|
return self.tree().a:spec
|
2009-10-10 19:47:14 -04:00
|
|
|
elseif a:spec =~# '^:[0-3]:'
|
|
|
|
return 'fugitive://'.self.dir().'//'.a:spec[1].'/'.a:spec[3:-1]
|
|
|
|
elseif a:spec ==# ':'
|
2012-03-18 21:55:53 -04:00
|
|
|
if $GIT_INDEX_FILE =~# '/[^/]*index[^/]*\.lock$' && fnamemodify($GIT_INDEX_FILE,':p')[0:strlen(self.dir())] ==# self.dir('') && filereadable($GIT_INDEX_FILE)
|
2010-01-09 18:19:07 -05:00
|
|
|
return fnamemodify($GIT_INDEX_FILE,':p')
|
|
|
|
else
|
|
|
|
return self.dir('index')
|
|
|
|
endif
|
2009-10-10 19:47:14 -04:00
|
|
|
elseif a:spec =~# '^:/'
|
|
|
|
let ref = self.rev_parse(matchstr(a:spec,'.[^:]*'))
|
|
|
|
return 'fugitive://'.self.dir().'//'.ref
|
|
|
|
elseif a:spec =~# '^:'
|
|
|
|
return 'fugitive://'.self.dir().'//0/'.a:spec[1:-1]
|
|
|
|
elseif a:spec =~# 'HEAD\|^refs/' && a:spec !~ ':' && filereadable(self.dir(a:spec))
|
|
|
|
return self.dir(a:spec)
|
2012-03-18 21:55:53 -04:00
|
|
|
elseif filereadable(self.dir('refs/'.a:spec))
|
2009-10-10 19:47:14 -04:00
|
|
|
return self.dir('refs/'.a:spec)
|
2012-03-18 21:55:53 -04:00
|
|
|
elseif filereadable(self.dir('refs/tags/'.a:spec))
|
2009-10-10 19:47:14 -04:00
|
|
|
return self.dir('refs/tags/'.a:spec)
|
2012-03-18 21:55:53 -04:00
|
|
|
elseif filereadable(self.dir('refs/heads/'.a:spec))
|
2009-10-10 19:47:14 -04:00
|
|
|
return self.dir('refs/heads/'.a:spec)
|
2012-03-18 21:55:53 -04:00
|
|
|
elseif filereadable(self.dir('refs/remotes/'.a:spec))
|
2009-10-10 19:47:14 -04:00
|
|
|
return self.dir('refs/remotes/'.a:spec)
|
2012-03-18 21:55:53 -04:00
|
|
|
elseif filereadable(self.dir('refs/remotes/'.a:spec.'/HEAD'))
|
2009-10-10 19:47:14 -04:00
|
|
|
return self.dir('refs/remotes/'.a:spec,'/HEAD')
|
|
|
|
else
|
|
|
|
try
|
|
|
|
let ref = self.rev_parse(matchstr(a:spec,'[^:]*'))
|
|
|
|
let path = s:sub(matchstr(a:spec,':.*'),'^:','/')
|
|
|
|
return 'fugitive://'.self.dir().'//'.ref.path
|
|
|
|
catch /^fugitive:/
|
|
|
|
return self.tree(a:spec)
|
|
|
|
endtry
|
|
|
|
endif
|
|
|
|
endfunction
|
|
|
|
|
2012-04-17 15:28:11 -04:00
|
|
|
function! s:repo_head(...) dict abort
|
|
|
|
let head = s:repo().head_ref()
|
|
|
|
|
|
|
|
if head =~# '^ref: '
|
|
|
|
let branch = s:sub(head,'^ref: %(refs/%(heads/|remotes/|tags/)=)=','')
|
|
|
|
elseif head =~# '^\x\{40\}$'
|
|
|
|
" truncate hash to a:1 characters if we're in detached head mode
|
|
|
|
let len = a:0 ? a:1 : 0
|
|
|
|
let branch = len ? head[0:len-1] : ''
|
2014-03-30 13:13:46 -04:00
|
|
|
else
|
|
|
|
return ''
|
2012-04-17 15:28:11 -04:00
|
|
|
endif
|
|
|
|
|
|
|
|
return branch
|
|
|
|
endfunction
|
|
|
|
|
2014-11-06 13:38:07 -05:00
|
|
|
call s:add_methods('repo',['dir','tree','bare','translate','head'])
|
2009-10-10 19:47:14 -04:00
|
|
|
|
|
|
|
function! s:repo_git_command(...) dict abort
|
|
|
|
let git = g:fugitive_git_executable . ' --git-dir='.s:shellesc(self.git_dir)
|
|
|
|
return git.join(map(copy(a:000),'" ".s:shellesc(v:val)'),'')
|
|
|
|
endfunction
|
|
|
|
|
|
|
|
function! s:repo_git_chomp(...) dict abort
|
|
|
|
return s:sub(system(call(self.git_command,a:000,self)),'\n$','')
|
|
|
|
endfunction
|
|
|
|
|
|
|
|
function! s:repo_git_chomp_in_tree(...) dict abort
|
|
|
|
let cd = exists('*haslocaldir') && haslocaldir() ? 'lcd ' : 'cd '
|
|
|
|
let dir = getcwd()
|
|
|
|
try
|
2010-01-13 17:50:18 -05:00
|
|
|
execute cd.'`=s:repo().tree()`'
|
2009-10-10 19:47:14 -04:00
|
|
|
return call(s:repo().git_chomp, a:000, s:repo())
|
|
|
|
finally
|
2010-01-13 17:50:18 -05:00
|
|
|
execute cd.'`=dir`'
|
2009-10-10 19:47:14 -04:00
|
|
|
endtry
|
|
|
|
endfunction
|
|
|
|
|
|
|
|
function! s:repo_rev_parse(rev) dict abort
|
|
|
|
let hash = self.git_chomp('rev-parse','--verify',a:rev)
|
2011-02-26 13:45:24 -05:00
|
|
|
if hash =~ '\<\x\{40\}$'
|
|
|
|
return matchstr(hash,'\<\x\{40\}$')
|
2009-10-10 19:47:14 -04:00
|
|
|
endif
|
2009-11-10 21:17:21 -05:00
|
|
|
call s:throw('rev-parse '.a:rev.': '.hash)
|
2009-10-10 19:47:14 -04:00
|
|
|
endfunction
|
|
|
|
|
|
|
|
call s:add_methods('repo',['git_command','git_chomp','git_chomp_in_tree','rev_parse'])
|
|
|
|
|
|
|
|
function! s:repo_dirglob(base) dict abort
|
|
|
|
let base = s:sub(a:base,'^/','')
|
|
|
|
let matches = split(glob(self.tree(s:gsub(base,'/','*&').'*/')),"\n")
|
|
|
|
call map(matches,'v:val[ strlen(self.tree())+(a:base !~ "^/") : -1 ]')
|
|
|
|
return matches
|
|
|
|
endfunction
|
|
|
|
|
|
|
|
function! s:repo_superglob(base) dict abort
|
|
|
|
if a:base =~# '^/' || a:base !~# ':'
|
|
|
|
let results = []
|
|
|
|
if a:base !~# '^/'
|
|
|
|
let heads = ["HEAD","ORIG_HEAD","FETCH_HEAD","MERGE_HEAD"]
|
|
|
|
let heads += sort(split(s:repo().git_chomp("rev-parse","--symbolic","--branches","--tags","--remotes"),"\n"))
|
|
|
|
call filter(heads,'v:val[ 0 : strlen(a:base)-1 ] ==# a:base')
|
|
|
|
let results += heads
|
|
|
|
endif
|
|
|
|
if !self.bare()
|
|
|
|
let base = s:sub(a:base,'^/','')
|
|
|
|
let matches = split(glob(self.tree(s:gsub(base,'/','*&').'*')),"\n")
|
2010-03-09 19:03:44 -05:00
|
|
|
call map(matches,'s:shellslash(v:val)')
|
2009-10-10 19:47:14 -04:00
|
|
|
call map(matches,'v:val !~ "/$" && isdirectory(v:val) ? v:val."/" : v:val')
|
|
|
|
call map(matches,'v:val[ strlen(self.tree())+(a:base !~ "^/") : -1 ]')
|
|
|
|
let results += matches
|
|
|
|
endif
|
|
|
|
return results
|
|
|
|
|
|
|
|
elseif a:base =~# '^:'
|
|
|
|
let entries = split(self.git_chomp('ls-files','--stage'),"\n")
|
|
|
|
call map(entries,'s:sub(v:val,".*(\\d)\\t(.*)",":\\1:\\2")')
|
|
|
|
if a:base !~# '^:[0-3]\%(:\|$\)'
|
|
|
|
call filter(entries,'v:val[1] == "0"')
|
|
|
|
call map(entries,'v:val[2:-1]')
|
|
|
|
endif
|
|
|
|
call filter(entries,'v:val[ 0 : strlen(a:base)-1 ] ==# a:base')
|
|
|
|
return entries
|
|
|
|
|
|
|
|
else
|
|
|
|
let tree = matchstr(a:base,'.*[:/]')
|
|
|
|
let entries = split(self.git_chomp('ls-tree',tree),"\n")
|
|
|
|
call map(entries,'s:sub(v:val,"^04.*\\zs$","/")')
|
|
|
|
call map(entries,'tree.s:sub(v:val,".*\t","")')
|
|
|
|
return filter(entries,'v:val[ 0 : strlen(a:base)-1 ] ==# a:base')
|
|
|
|
endif
|
|
|
|
endfunction
|
|
|
|
|
|
|
|
call s:add_methods('repo',['dirglob','superglob'])
|
|
|
|
|
2011-08-21 13:52:33 -04:00
|
|
|
function! s:repo_config(conf) dict abort
|
|
|
|
return matchstr(system(s:repo().git_command('config').' '.a:conf),"[^\r\n]*")
|
|
|
|
endfun
|
|
|
|
|
|
|
|
function! s:repo_user() dict abort
|
|
|
|
let username = s:repo().config('user.name')
|
|
|
|
let useremail = s:repo().config('user.email')
|
|
|
|
return username.' <'.useremail.'>'
|
|
|
|
endfun
|
|
|
|
|
|
|
|
function! s:repo_aliases() dict abort
|
|
|
|
if !has_key(self,'_aliases')
|
|
|
|
let self._aliases = {}
|
|
|
|
for line in split(self.git_chomp('config','--get-regexp','^alias[.]'),"\n")
|
|
|
|
let self._aliases[matchstr(line,'\.\zs\S\+')] = matchstr(line,' \zs.*')
|
|
|
|
endfor
|
|
|
|
endif
|
|
|
|
return self._aliases
|
|
|
|
endfunction
|
|
|
|
|
|
|
|
call s:add_methods('repo',['config', 'user', 'aliases'])
|
|
|
|
|
2009-10-10 19:47:14 -04:00
|
|
|
function! s:repo_keywordprg() dict abort
|
2012-10-09 18:35:44 -04:00
|
|
|
let args = ' --git-dir='.escape(self.dir(),"\\\"' ")
|
2010-03-08 22:57:18 -05:00
|
|
|
if has('gui_running') && !has('win32')
|
2012-10-09 18:35:44 -04:00
|
|
|
return g:fugitive_git_executable . ' --no-pager' . args . ' log -1'
|
2009-10-10 19:47:14 -04:00
|
|
|
else
|
2012-10-09 18:35:44 -04:00
|
|
|
return g:fugitive_git_executable . args . ' show'
|
2009-10-10 19:47:14 -04:00
|
|
|
endif
|
|
|
|
endfunction
|
|
|
|
|
|
|
|
call s:add_methods('repo',['keywordprg'])
|
|
|
|
|
2014-06-21 08:48:11 -04:00
|
|
|
" Section: Buffer
|
2009-10-10 19:47:14 -04:00
|
|
|
|
|
|
|
let s:buffer_prototype = {}
|
|
|
|
|
|
|
|
function! s:buffer(...) abort
|
|
|
|
let buffer = {'#': bufnr(a:0 ? a:1 : '%')}
|
|
|
|
call extend(extend(buffer,s:buffer_prototype,'keep'),s:abstract_prototype,'keep')
|
2009-11-10 21:17:21 -05:00
|
|
|
if buffer.getvar('git_dir') !=# ''
|
|
|
|
return buffer
|
2009-10-10 19:47:14 -04:00
|
|
|
endif
|
2009-11-10 21:17:21 -05:00
|
|
|
call s:throw('not a git repository: '.expand('%:p'))
|
2009-10-10 19:47:14 -04:00
|
|
|
endfunction
|
|
|
|
|
|
|
|
function! fugitive#buffer(...) abort
|
|
|
|
return s:buffer(a:0 ? a:1 : '%')
|
|
|
|
endfunction
|
|
|
|
|
|
|
|
function! s:buffer_getvar(var) dict abort
|
2014-04-01 18:59:01 -04:00
|
|
|
return getbufvar(self['#'],a:var)
|
2009-10-10 19:47:14 -04:00
|
|
|
endfunction
|
|
|
|
|
2009-12-13 19:49:35 -05:00
|
|
|
function! s:buffer_setvar(var,value) dict abort
|
2014-04-01 18:59:01 -04:00
|
|
|
return setbufvar(self['#'],a:var,a:value)
|
2009-12-13 19:49:35 -05:00
|
|
|
endfunction
|
|
|
|
|
2009-10-10 19:47:14 -04:00
|
|
|
function! s:buffer_getline(lnum) dict abort
|
2014-04-01 18:59:01 -04:00
|
|
|
return get(getbufline(self['#'], a:lnum), 0, '')
|
2009-10-10 19:47:14 -04:00
|
|
|
endfunction
|
|
|
|
|
|
|
|
function! s:buffer_repo() dict abort
|
|
|
|
return s:repo(self.getvar('git_dir'))
|
|
|
|
endfunction
|
|
|
|
|
|
|
|
function! s:buffer_type(...) dict abort
|
|
|
|
if self.getvar('fugitive_type') != ''
|
|
|
|
let type = self.getvar('fugitive_type')
|
2010-08-03 15:23:25 -04:00
|
|
|
elseif fnamemodify(self.spec(),':p') =~# '.\git/refs/\|\.git/\w*HEAD$'
|
2009-10-10 19:47:14 -04:00
|
|
|
let type = 'head'
|
|
|
|
elseif self.getline(1) =~ '^tree \x\{40\}$' && self.getline(2) == ''
|
|
|
|
let type = 'tree'
|
|
|
|
elseif self.getline(1) =~ '^\d\{6\} \w\{4\} \x\{40\}\>\t'
|
|
|
|
let type = 'tree'
|
|
|
|
elseif self.getline(1) =~ '^\d\{6\} \x\{40\}\> \d\t'
|
|
|
|
let type = 'index'
|
2010-08-03 15:23:25 -04:00
|
|
|
elseif isdirectory(self.spec())
|
2009-10-10 19:47:14 -04:00
|
|
|
let type = 'directory'
|
2010-08-03 15:23:25 -04:00
|
|
|
elseif self.spec() == ''
|
2010-02-07 21:54:07 -05:00
|
|
|
let type = 'null'
|
2009-10-10 19:47:14 -04:00
|
|
|
else
|
2011-08-25 20:24:01 -04:00
|
|
|
let type = 'file'
|
2009-10-10 19:47:14 -04:00
|
|
|
endif
|
|
|
|
if a:0
|
|
|
|
return !empty(filter(copy(a:000),'v:val ==# type'))
|
|
|
|
else
|
|
|
|
return type
|
|
|
|
endif
|
|
|
|
endfunction
|
|
|
|
|
2010-12-03 01:38:26 -05:00
|
|
|
if has('win32')
|
|
|
|
|
|
|
|
function! s:buffer_spec() dict abort
|
|
|
|
let bufname = bufname(self['#'])
|
|
|
|
let retval = ''
|
|
|
|
for i in split(bufname,'[^:]\zs\\')
|
|
|
|
let retval = fnamemodify((retval==''?'':retval.'\').i,':.')
|
|
|
|
endfor
|
|
|
|
return s:shellslash(fnamemodify(retval,':p'))
|
|
|
|
endfunction
|
|
|
|
|
|
|
|
else
|
|
|
|
|
|
|
|
function! s:buffer_spec() dict abort
|
|
|
|
let bufname = bufname(self['#'])
|
|
|
|
return s:shellslash(bufname == '' ? '' : fnamemodify(bufname,':p'))
|
|
|
|
endfunction
|
|
|
|
|
|
|
|
endif
|
2009-10-10 19:47:14 -04:00
|
|
|
|
2010-08-03 15:23:25 -04:00
|
|
|
function! s:buffer_name() dict abort
|
|
|
|
return self.spec()
|
|
|
|
endfunction
|
|
|
|
|
2009-10-10 19:47:14 -04:00
|
|
|
function! s:buffer_commit() dict abort
|
2010-08-03 15:23:25 -04:00
|
|
|
return matchstr(self.spec(),'^fugitive://.\{-\}//\zs\w*')
|
2009-10-10 19:47:14 -04:00
|
|
|
endfunction
|
|
|
|
|
2015-06-30 17:42:13 -04:00
|
|
|
function! s:cpath(path) abort
|
2015-07-01 10:55:35 -04:00
|
|
|
if exists('+fileignorecase') && &fileignorecase
|
2015-06-30 17:42:13 -04:00
|
|
|
return tolower(a:path)
|
|
|
|
else
|
|
|
|
return a:path
|
|
|
|
endif
|
|
|
|
endfunction
|
|
|
|
|
2009-10-10 19:47:14 -04:00
|
|
|
function! s:buffer_path(...) dict abort
|
2010-08-03 15:23:25 -04:00
|
|
|
let rev = matchstr(self.spec(),'^fugitive://.\{-\}//\zs.*')
|
2009-10-10 19:47:14 -04:00
|
|
|
if rev != ''
|
|
|
|
let rev = s:sub(rev,'\w*','')
|
2015-06-30 17:42:13 -04:00
|
|
|
elseif s:cpath(self.spec()[0 : len(self.repo().dir())]) ==#
|
|
|
|
\ s:cpath(self.repo().dir() . '/')
|
2011-10-08 16:03:50 -04:00
|
|
|
let rev = '/.git'.self.spec()[strlen(self.repo().dir()) : -1]
|
2015-06-30 17:42:13 -04:00
|
|
|
elseif !self.repo().bare() &&
|
|
|
|
\ s:cpath(self.spec()[0 : len(self.repo().tree())]) ==#
|
|
|
|
\ s:cpath(self.repo().tree() . '/')
|
2010-08-03 15:23:25 -04:00
|
|
|
let rev = self.spec()[strlen(self.repo().tree()) : -1]
|
2009-10-10 19:47:14 -04:00
|
|
|
endif
|
2010-09-09 11:51:04 -04:00
|
|
|
return s:sub(s:sub(rev,'.\zs/$',''),'^/',a:0 ? a:1 : '')
|
2009-10-10 19:47:14 -04:00
|
|
|
endfunction
|
|
|
|
|
|
|
|
function! s:buffer_rev() dict abort
|
2010-08-03 15:23:25 -04:00
|
|
|
let rev = matchstr(self.spec(),'^fugitive://.\{-\}//\zs.*')
|
2009-10-10 19:47:14 -04:00
|
|
|
if rev =~ '^\x/'
|
|
|
|
return ':'.rev[0].':'.rev[2:-1]
|
|
|
|
elseif rev =~ '.'
|
|
|
|
return s:sub(rev,'/',':')
|
2010-08-03 15:23:25 -04:00
|
|
|
elseif self.spec() =~ '\.git/index$'
|
2009-10-10 19:47:14 -04:00
|
|
|
return ':'
|
2010-08-03 15:23:25 -04:00
|
|
|
elseif self.spec() =~ '\.git/refs/\|\.git/.*HEAD$'
|
|
|
|
return self.spec()[strlen(self.repo().dir())+1 : -1]
|
2009-10-10 19:47:14 -04:00
|
|
|
else
|
2012-04-07 15:42:09 -04:00
|
|
|
return self.path('/')
|
2009-10-10 19:47:14 -04:00
|
|
|
endif
|
|
|
|
endfunction
|
|
|
|
|
|
|
|
function! s:buffer_sha1() dict abort
|
2010-08-03 15:23:25 -04:00
|
|
|
if self.spec() =~ '^fugitive://' || self.spec() =~ '\.git/refs/\|\.git/.*HEAD$'
|
2009-10-10 19:47:14 -04:00
|
|
|
return self.repo().rev_parse(self.rev())
|
|
|
|
else
|
|
|
|
return ''
|
|
|
|
endif
|
|
|
|
endfunction
|
|
|
|
|
|
|
|
function! s:buffer_expand(rev) dict abort
|
|
|
|
if a:rev =~# '^:[0-3]$'
|
|
|
|
let file = a:rev.self.path(':')
|
2011-02-26 12:39:13 -05:00
|
|
|
elseif a:rev =~# '^[-:]/$'
|
|
|
|
let file = '/'.self.path()
|
2009-10-10 19:47:14 -04:00
|
|
|
elseif a:rev =~# '^-'
|
|
|
|
let file = 'HEAD^{}'.a:rev[1:-1].self.path(':')
|
|
|
|
elseif a:rev =~# '^@{'
|
|
|
|
let file = 'HEAD'.a:rev.self.path(':')
|
|
|
|
elseif a:rev =~# '^[~^]'
|
|
|
|
let commit = s:sub(self.commit(),'^\d=$','HEAD')
|
|
|
|
let file = commit.a:rev.self.path(':')
|
|
|
|
else
|
|
|
|
let file = a:rev
|
|
|
|
endif
|
2011-02-26 12:39:13 -05:00
|
|
|
return s:sub(s:sub(file,'\%$',self.path()),'\.\@<=/$','')
|
2009-10-10 19:47:14 -04:00
|
|
|
endfunction
|
|
|
|
|
|
|
|
function! s:buffer_containing_commit() dict abort
|
2009-11-11 00:16:02 -05:00
|
|
|
if self.commit() =~# '^\d$'
|
2009-10-10 19:47:14 -04:00
|
|
|
return ':'
|
2009-11-11 00:16:02 -05:00
|
|
|
elseif self.commit() =~# '.'
|
|
|
|
return self.commit()
|
2009-10-10 19:47:14 -04:00
|
|
|
else
|
|
|
|
return 'HEAD'
|
|
|
|
endif
|
|
|
|
endfunction
|
|
|
|
|
2012-04-07 16:14:51 -04:00
|
|
|
function! s:buffer_up(...) dict abort
|
|
|
|
let rev = self.rev()
|
|
|
|
let c = a:0 ? a:1 : 1
|
|
|
|
while c
|
|
|
|
if rev =~# '^[/:]$'
|
|
|
|
let rev = 'HEAD'
|
|
|
|
elseif rev =~# '^:'
|
|
|
|
let rev = ':'
|
2012-04-07 16:23:49 -04:00
|
|
|
elseif rev =~# '^refs/[^^~:]*$\|^[^^~:]*HEAD$'
|
2012-04-07 16:14:51 -04:00
|
|
|
let rev .= '^{}'
|
|
|
|
elseif rev =~# '^/\|:.*/'
|
|
|
|
let rev = s:sub(rev, '.*\zs/.*', '')
|
|
|
|
elseif rev =~# ':.'
|
|
|
|
let rev = matchstr(rev, '^[^:]*:')
|
|
|
|
elseif rev =~# ':$'
|
|
|
|
let rev = rev[0:-2]
|
|
|
|
else
|
|
|
|
return rev.'~'.c
|
|
|
|
endif
|
|
|
|
let c -= 1
|
|
|
|
endwhile
|
|
|
|
return rev
|
|
|
|
endfunction
|
|
|
|
|
|
|
|
call s:add_methods('buffer',['getvar','setvar','getline','repo','type','spec','name','commit','path','rev','sha1','expand','containing_commit','up'])
|
2009-10-10 19:47:14 -04:00
|
|
|
|
2014-06-21 08:48:11 -04:00
|
|
|
" Section: Git
|
2009-10-10 19:47:14 -04:00
|
|
|
|
2010-03-19 19:59:08 -04:00
|
|
|
call s:command("-bang -nargs=? -complete=customlist,s:GitComplete Git :execute s:Git(<bang>0,<q-args>)")
|
2009-10-10 19:47:14 -04:00
|
|
|
|
|
|
|
function! s:ExecuteInTree(cmd) abort
|
|
|
|
let cd = exists('*haslocaldir') && haslocaldir() ? 'lcd ' : 'cd '
|
|
|
|
let dir = getcwd()
|
|
|
|
try
|
2010-01-13 17:50:18 -05:00
|
|
|
execute cd.'`=s:repo().tree()`'
|
2009-10-10 19:47:14 -04:00
|
|
|
execute a:cmd
|
|
|
|
finally
|
2010-01-13 17:50:18 -05:00
|
|
|
execute cd.'`=dir`'
|
2009-10-10 19:47:14 -04:00
|
|
|
endtry
|
|
|
|
endfunction
|
|
|
|
|
2014-06-11 03:30:27 -04:00
|
|
|
function! s:Git(bang, args) abort
|
2011-08-19 02:43:31 -04:00
|
|
|
if a:bang
|
2014-06-11 03:30:27 -04:00
|
|
|
return s:Edit('edit', 1, a:args)
|
2011-08-19 02:43:31 -04:00
|
|
|
endif
|
2014-06-11 03:30:27 -04:00
|
|
|
let git = g:fugitive_git_executable
|
2010-03-08 22:57:18 -05:00
|
|
|
if has('gui_running') && !has('win32')
|
2009-10-10 19:47:14 -04:00
|
|
|
let git .= ' --no-pager'
|
|
|
|
endif
|
2014-06-11 03:30:27 -04:00
|
|
|
let args = matchstr(a:args,'\v\C.{-}%($|\\@<!%(\\\\)*\|)@=')
|
2015-03-28 11:11:07 -04:00
|
|
|
if exists(':terminal')
|
|
|
|
let dir = s:repo().tree()
|
|
|
|
tabnew
|
|
|
|
execute 'lcd' fnameescape(dir)
|
|
|
|
execute 'terminal' git args
|
|
|
|
else
|
|
|
|
call s:ExecuteInTree('!'.git.' '.args)
|
|
|
|
if has('win32')
|
|
|
|
call fugitive#reload_status()
|
|
|
|
endif
|
|
|
|
endif
|
2014-06-11 03:30:27 -04:00
|
|
|
return matchstr(a:args, '\v\C\\@<!%(\\\\)*\|\zs.*')
|
2009-10-10 19:47:14 -04:00
|
|
|
endfunction
|
|
|
|
|
2014-06-29 10:53:52 -04:00
|
|
|
function! fugitive#git_commands() abort
|
2009-10-10 19:47:14 -04:00
|
|
|
if !exists('s:exec_path')
|
|
|
|
let s:exec_path = s:sub(system(g:fugitive_git_executable.' --exec-path'),'\n$','')
|
|
|
|
endif
|
2014-06-29 10:53:52 -04:00
|
|
|
return map(split(glob(s:exec_path.'/git-*'),"\n"),'s:sub(v:val[strlen(s:exec_path)+5 : -1],"\\.exe$","")')
|
|
|
|
endfunction
|
|
|
|
|
2014-06-29 10:58:41 -04:00
|
|
|
function! s:GitComplete(A, L, P) abort
|
|
|
|
if strpart(a:L, 0, a:P) !~# ' [[:alnum:]-]\+ '
|
|
|
|
let cmds = fugitive#git_commands()
|
2014-06-17 02:30:30 -04:00
|
|
|
return filter(sort(cmds+keys(s:repo().aliases())), 'strpart(v:val, 0, strlen(a:A)) ==# a:A')
|
2014-06-29 10:58:41 -04:00
|
|
|
else
|
|
|
|
return s:repo().superglob(a:A)
|
2009-10-10 19:47:14 -04:00
|
|
|
endif
|
|
|
|
endfunction
|
|
|
|
|
2014-06-21 08:48:11 -04:00
|
|
|
" Section: Gcd, Glcd
|
2009-10-10 19:47:14 -04:00
|
|
|
|
|
|
|
function! s:DirComplete(A,L,P) abort
|
|
|
|
let matches = s:repo().dirglob(a:A)
|
|
|
|
return matches
|
|
|
|
endfunction
|
|
|
|
|
|
|
|
call s:command("-bar -bang -nargs=? -complete=customlist,s:DirComplete Gcd :cd<bang> `=s:repo().bare() ? s:repo().dir(<q-args>) : s:repo().tree(<q-args>)`")
|
|
|
|
call s:command("-bar -bang -nargs=? -complete=customlist,s:DirComplete Glcd :lcd<bang> `=s:repo().bare() ? s:repo().dir(<q-args>) : s:repo().tree(<q-args>)`")
|
|
|
|
|
2014-06-21 08:48:11 -04:00
|
|
|
" Section: Gstatus
|
2009-10-19 22:11:40 -04:00
|
|
|
|
|
|
|
call s:command("-bar Gstatus :execute s:Status()")
|
2013-03-12 02:01:49 -04:00
|
|
|
augroup fugitive_status
|
|
|
|
autocmd!
|
|
|
|
if !has('win32')
|
|
|
|
autocmd FocusGained,ShellCmdPost * call fugitive#reload_status()
|
2015-03-28 11:11:07 -04:00
|
|
|
autocmd BufDelete term://* call fugitive#reload_status()
|
2013-03-12 02:01:49 -04:00
|
|
|
endif
|
|
|
|
augroup END
|
2009-10-19 22:11:40 -04:00
|
|
|
|
2010-01-09 17:01:44 -05:00
|
|
|
function! s:Status() abort
|
2009-10-19 22:11:40 -04:00
|
|
|
try
|
|
|
|
Gpedit :
|
|
|
|
wincmd P
|
2013-09-14 08:37:03 -04:00
|
|
|
setlocal foldmethod=syntax foldlevel=1
|
2011-09-02 15:19:06 -04:00
|
|
|
nnoremap <buffer> <silent> q :<C-U>bdelete<CR>
|
2009-10-19 22:11:40 -04:00
|
|
|
catch /^fugitive:/
|
|
|
|
return 'echoerr v:errmsg'
|
|
|
|
endtry
|
|
|
|
return ''
|
|
|
|
endfunction
|
|
|
|
|
2010-01-09 17:01:44 -05:00
|
|
|
function! fugitive#reload_status() abort
|
2013-03-12 02:01:49 -04:00
|
|
|
if exists('s:reloading_status')
|
|
|
|
return
|
|
|
|
endif
|
|
|
|
try
|
|
|
|
let s:reloading_status = 1
|
|
|
|
let mytab = tabpagenr()
|
|
|
|
for tab in [mytab] + range(1,tabpagenr('$'))
|
|
|
|
for winnr in range(1,tabpagewinnr(tab,'$'))
|
|
|
|
if getbufvar(tabpagebuflist(tab)[winnr-1],'fugitive_type') ==# 'index'
|
|
|
|
execute 'tabnext '.tab
|
|
|
|
if winnr != winnr()
|
|
|
|
execute winnr.'wincmd w'
|
|
|
|
let restorewinnr = 1
|
2009-10-19 22:11:40 -04:00
|
|
|
endif
|
2013-03-12 02:01:49 -04:00
|
|
|
try
|
|
|
|
if !&modified
|
|
|
|
call s:BufReadIndex()
|
|
|
|
endif
|
|
|
|
finally
|
|
|
|
if exists('restorewinnr')
|
|
|
|
wincmd p
|
|
|
|
endif
|
|
|
|
execute 'tabnext '.mytab
|
|
|
|
endtry
|
|
|
|
endif
|
|
|
|
endfor
|
2009-10-19 22:11:40 -04:00
|
|
|
endfor
|
2013-03-12 02:01:49 -04:00
|
|
|
finally
|
|
|
|
unlet! s:reloading_status
|
|
|
|
endtry
|
2009-10-19 22:11:40 -04:00
|
|
|
endfunction
|
|
|
|
|
2012-07-16 18:10:27 -04:00
|
|
|
function! s:stage_info(lnum) abort
|
2012-07-28 11:54:52 -04:00
|
|
|
let filename = matchstr(getline(a:lnum),'^#\t\zs.\{-\}\ze\%( ([^()[:digit:]]\+)\)\=$')
|
2012-07-16 11:16:35 -04:00
|
|
|
let lnum = a:lnum
|
2013-02-10 13:01:22 -05:00
|
|
|
if has('multi_byte_encoding')
|
|
|
|
let colon = '\%(:\|\%uff1a\)'
|
|
|
|
else
|
|
|
|
let colon = ':'
|
|
|
|
endif
|
2013-01-09 23:11:30 -05:00
|
|
|
while lnum && getline(lnum) !~# colon.'$'
|
2012-07-16 11:16:35 -04:00
|
|
|
let lnum -= 1
|
|
|
|
endwhile
|
|
|
|
if !lnum
|
2012-07-16 18:10:27 -04:00
|
|
|
return ['', '']
|
2014-03-05 17:57:43 -05:00
|
|
|
elseif (getline(lnum+1) =~# '^# .*\<git \%(reset\|rm --cached\) ' && getline(lnum+2) ==# '#') || getline(lnum) ==# '# Changes to be committed:'
|
2013-01-09 23:11:30 -05:00
|
|
|
return [matchstr(filename, colon.' *\zs.*'), 'staged']
|
2014-06-20 07:52:06 -04:00
|
|
|
elseif (getline(lnum+1) =~# '^# .*\<git add ' && getline(lnum+2) ==# '#' && getline(lnum+3) !~# colon.' ') || getline(lnum) ==# '# Untracked files:'
|
2014-03-05 17:57:43 -05:00
|
|
|
return [filename, 'untracked']
|
2013-06-05 21:35:15 -04:00
|
|
|
elseif getline(lnum+2) =~# '^# .*\<git checkout ' || getline(lnum) ==# '# Changes not staged for commit:'
|
2013-01-09 23:11:30 -05:00
|
|
|
return [matchstr(filename, colon.' *\zs.*'), 'unstaged']
|
2014-03-05 17:57:43 -05:00
|
|
|
elseif getline(lnum+2) =~# '^# .*\<git \%(add\|rm\)' || getline(lnum) ==# '# Unmerged paths:'
|
2013-01-09 23:11:30 -05:00
|
|
|
return [matchstr(filename, colon.' *\zs.*'), 'unmerged']
|
2012-07-28 11:54:52 -04:00
|
|
|
else
|
2014-03-05 17:57:43 -05:00
|
|
|
return ['', 'unknown']
|
2012-07-16 11:16:35 -04:00
|
|
|
endif
|
|
|
|
endfunction
|
|
|
|
|
2014-03-27 17:22:35 -04:00
|
|
|
function! s:StageNext(count) abort
|
2012-09-07 01:07:54 -04:00
|
|
|
for i in range(a:count)
|
|
|
|
call search('^#\t.*','W')
|
|
|
|
endfor
|
|
|
|
return '.'
|
|
|
|
endfunction
|
|
|
|
|
2014-03-27 17:22:35 -04:00
|
|
|
function! s:StagePrevious(count) abort
|
2014-04-10 14:53:49 -04:00
|
|
|
if line('.') == 1 && exists(':CtrlP') && get(g:, 'ctrl_p_map') =~? '^<c-p>$'
|
2012-09-07 01:15:48 -04:00
|
|
|
return 'CtrlP '.fnameescape(s:repo().tree())
|
|
|
|
else
|
|
|
|
for i in range(a:count)
|
|
|
|
call search('^#\t.*','Wbe')
|
|
|
|
endfor
|
|
|
|
return '.'
|
|
|
|
endif
|
2012-09-07 01:07:54 -04:00
|
|
|
endfunction
|
|
|
|
|
2014-03-27 17:22:35 -04:00
|
|
|
function! s:StageReloadSeek(target,lnum1,lnum2) abort
|
2011-08-21 13:45:21 -04:00
|
|
|
let jump = a:target
|
2013-01-09 23:11:30 -05:00
|
|
|
let f = matchstr(getline(a:lnum1-1),'^#\t\%([[:alpha:] ]\+: *\|.*\%uff1a *\)\=\zs.*')
|
2011-08-21 13:45:21 -04:00
|
|
|
if f !=# '' | let jump = f | endif
|
2013-01-09 23:11:30 -05:00
|
|
|
let f = matchstr(getline(a:lnum2+1),'^#\t\%([[:alpha:] ]\+: *\|.*\%uff1a *\)\=\zs.*')
|
2011-08-21 13:45:21 -04:00
|
|
|
if f !=# '' | let jump = f | endif
|
|
|
|
silent! edit!
|
|
|
|
1
|
|
|
|
redraw
|
2013-01-09 23:11:30 -05:00
|
|
|
call search('^#\t\%([[:alpha:] ]\+: *\|.*\%uff1a *\)\=\V'.jump.'\%( ([^()[:digit:]]\+)\)\=\$','W')
|
2011-08-21 13:45:21 -04:00
|
|
|
endfunction
|
|
|
|
|
2014-06-21 10:05:46 -04:00
|
|
|
function! s:StageUndo() abort
|
|
|
|
let [filename, section] = s:stage_info(line('.'))
|
|
|
|
if empty(filename)
|
|
|
|
return ''
|
|
|
|
endif
|
|
|
|
let repo = s:repo()
|
|
|
|
let hash = repo.git_chomp('hash-object', '-w', filename)
|
|
|
|
if !empty(hash)
|
|
|
|
if section ==# 'untracked'
|
|
|
|
call delete(s:repo().tree(filename))
|
|
|
|
elseif section ==# 'unstaged'
|
2014-06-25 10:29:17 -04:00
|
|
|
call repo.git_chomp_in_tree('checkout', '--', filename)
|
2014-06-21 10:05:46 -04:00
|
|
|
else
|
2014-06-25 10:29:17 -04:00
|
|
|
call repo.git_chomp_in_tree('checkout', 'HEAD', '--', filename)
|
2014-06-21 10:05:46 -04:00
|
|
|
endif
|
|
|
|
call s:StageReloadSeek(filename, line('.'), line('.'))
|
|
|
|
let @" = hash
|
|
|
|
return 'checktime|redraw|echomsg ' .
|
|
|
|
\ string('To restore, :Git cat-file blob '.hash[0:6].' > '.filename)
|
|
|
|
endif
|
|
|
|
endfunction
|
|
|
|
|
2011-08-19 15:01:37 -04:00
|
|
|
function! s:StageDiff(diff) abort
|
2012-07-16 18:10:27 -04:00
|
|
|
let [filename, section] = s:stage_info(line('.'))
|
2012-07-16 11:16:35 -04:00
|
|
|
if filename ==# '' && section ==# 'staged'
|
2013-05-17 23:58:10 -04:00
|
|
|
return 'Git! diff --no-ext-diff --cached'
|
2010-03-19 21:48:41 -04:00
|
|
|
elseif filename ==# ''
|
2013-05-17 23:58:10 -04:00
|
|
|
return 'Git! diff --no-ext-diff'
|
2012-07-16 18:10:27 -04:00
|
|
|
elseif filename =~# ' -> '
|
2010-03-19 21:23:41 -04:00
|
|
|
let [old, new] = split(filename,' -> ')
|
|
|
|
execute 'Gedit '.s:fnameescape(':0:'.new)
|
2011-08-19 15:01:37 -04:00
|
|
|
return a:diff.' HEAD:'.s:fnameescape(old)
|
2012-07-16 11:16:35 -04:00
|
|
|
elseif section ==# 'staged'
|
2010-03-19 21:23:41 -04:00
|
|
|
execute 'Gedit '.s:fnameescape(':0:'.filename)
|
2011-08-19 15:01:37 -04:00
|
|
|
return a:diff.' -'
|
2010-03-19 21:23:41 -04:00
|
|
|
else
|
|
|
|
execute 'Gedit '.s:fnameescape('/'.filename)
|
2011-08-19 15:01:37 -04:00
|
|
|
return a:diff
|
2010-03-19 21:23:41 -04:00
|
|
|
endif
|
|
|
|
endfunction
|
|
|
|
|
2011-08-19 15:13:44 -04:00
|
|
|
function! s:StageDiffEdit() abort
|
2012-07-16 18:10:27 -04:00
|
|
|
let [filename, section] = s:stage_info(line('.'))
|
2011-08-21 13:45:21 -04:00
|
|
|
let arg = (filename ==# '' ? '.' : filename)
|
2012-07-16 11:16:35 -04:00
|
|
|
if section ==# 'staged'
|
2013-05-17 23:58:10 -04:00
|
|
|
return 'Git! diff --no-ext-diff --cached '.s:shellesc(arg)
|
2012-07-16 11:16:35 -04:00
|
|
|
elseif section ==# 'untracked'
|
2011-08-21 13:45:21 -04:00
|
|
|
let repo = s:repo()
|
|
|
|
call repo.git_chomp_in_tree('add','--intent-to-add',arg)
|
|
|
|
if arg ==# '.'
|
|
|
|
silent! edit!
|
|
|
|
1
|
2012-08-01 16:00:02 -04:00
|
|
|
if !search('^# .*:\n#.*\n# .*"git checkout \|^# Changes not staged for commit:$','W')
|
2012-07-16 11:16:35 -04:00
|
|
|
call search('^# .*:$','W')
|
2011-08-21 13:45:21 -04:00
|
|
|
endif
|
|
|
|
else
|
|
|
|
call s:StageReloadSeek(arg,line('.'),line('.'))
|
|
|
|
endif
|
|
|
|
return ''
|
2011-08-19 15:13:44 -04:00
|
|
|
else
|
2013-05-17 23:58:10 -04:00
|
|
|
return 'Git! diff --no-ext-diff '.s:shellesc(arg)
|
2011-08-19 15:13:44 -04:00
|
|
|
endif
|
|
|
|
endfunction
|
|
|
|
|
2010-01-09 17:01:44 -05:00
|
|
|
function! s:StageToggle(lnum1,lnum2) abort
|
2013-03-29 22:58:23 -04:00
|
|
|
if a:lnum1 == 1 && a:lnum2 == 1
|
|
|
|
return 'Gedit /.git|call search("^index$", "wc")'
|
|
|
|
endif
|
2009-10-19 22:11:40 -04:00
|
|
|
try
|
2009-10-22 21:54:55 -04:00
|
|
|
let output = ''
|
|
|
|
for lnum in range(a:lnum1,a:lnum2)
|
2012-07-16 18:10:27 -04:00
|
|
|
let [filename, section] = s:stage_info(lnum)
|
2011-04-26 08:35:02 -04:00
|
|
|
let repo = s:repo()
|
2012-07-16 18:10:27 -04:00
|
|
|
if getline('.') =~# '^# .*:$'
|
2012-07-16 11:16:35 -04:00
|
|
|
if section ==# 'staged'
|
|
|
|
call repo.git_chomp_in_tree('reset','-q')
|
|
|
|
silent! edit!
|
|
|
|
1
|
2012-08-01 16:00:02 -04:00
|
|
|
if !search('^# .*:\n# .*"git add .*\n#\n\|^# Untracked files:$','W')
|
2012-07-16 11:16:35 -04:00
|
|
|
call search('^# .*:$','W')
|
|
|
|
endif
|
|
|
|
return ''
|
|
|
|
elseif section ==# 'unstaged'
|
|
|
|
call repo.git_chomp_in_tree('add','-u')
|
|
|
|
silent! edit!
|
|
|
|
1
|
2012-08-01 16:00:02 -04:00
|
|
|
if !search('^# .*:\n# .*"git add .*\n#\n\|^# Untracked files:$','W')
|
2012-07-16 11:16:35 -04:00
|
|
|
call search('^# .*:$','W')
|
|
|
|
endif
|
|
|
|
return ''
|
|
|
|
else
|
|
|
|
call repo.git_chomp_in_tree('add','.')
|
|
|
|
silent! edit!
|
|
|
|
1
|
|
|
|
call search('^# .*:$','W')
|
|
|
|
return ''
|
2011-04-23 22:15:28 -04:00
|
|
|
endif
|
2010-01-09 23:31:22 -05:00
|
|
|
endif
|
2009-10-22 21:54:55 -04:00
|
|
|
if filename ==# ''
|
|
|
|
continue
|
|
|
|
endif
|
|
|
|
execute lnum
|
2012-07-16 18:10:27 -04:00
|
|
|
if filename =~ ' -> '
|
2009-10-22 21:54:55 -04:00
|
|
|
let cmd = ['mv','--'] + reverse(split(filename,' -> '))
|
|
|
|
let filename = cmd[-1]
|
2012-07-16 11:16:35 -04:00
|
|
|
elseif section ==# 'staged'
|
2009-10-22 21:54:55 -04:00
|
|
|
let cmd = ['reset','-q','--',filename]
|
2012-07-16 18:10:27 -04:00
|
|
|
elseif getline(lnum) =~# '^#\tdeleted:'
|
2009-10-22 21:54:55 -04:00
|
|
|
let cmd = ['rm','--',filename]
|
2012-07-28 11:54:52 -04:00
|
|
|
elseif getline(lnum) =~# '^#\tmodified:'
|
2009-10-22 21:54:55 -04:00
|
|
|
let cmd = ['add','--',filename]
|
2012-07-28 11:54:52 -04:00
|
|
|
else
|
|
|
|
let cmd = ['add','-A','--',filename]
|
2009-10-22 21:54:55 -04:00
|
|
|
endif
|
2014-06-21 11:28:33 -04:00
|
|
|
if !exists('first_filename')
|
|
|
|
let first_filename = filename
|
|
|
|
endif
|
2011-04-26 08:35:02 -04:00
|
|
|
let output .= call(repo.git_chomp_in_tree,cmd,s:repo())."\n"
|
2009-10-22 21:54:55 -04:00
|
|
|
endfor
|
|
|
|
if exists('first_filename')
|
2011-08-21 13:45:21 -04:00
|
|
|
call s:StageReloadSeek(first_filename,a:lnum1,a:lnum2)
|
2009-10-19 22:11:40 -04:00
|
|
|
endif
|
2009-10-22 21:54:55 -04:00
|
|
|
echo s:sub(s:gsub(output,'\n+','\n'),'\n$','')
|
2009-10-19 22:11:40 -04:00
|
|
|
catch /^fugitive:/
|
|
|
|
return 'echoerr v:errmsg'
|
|
|
|
endtry
|
|
|
|
return 'checktime'
|
|
|
|
endfunction
|
|
|
|
|
2010-01-11 22:51:54 -05:00
|
|
|
function! s:StagePatch(lnum1,lnum2) abort
|
|
|
|
let add = []
|
|
|
|
let reset = []
|
|
|
|
|
|
|
|
for lnum in range(a:lnum1,a:lnum2)
|
2012-07-16 18:10:27 -04:00
|
|
|
let [filename, section] = s:stage_info(lnum)
|
|
|
|
if getline('.') =~# '^# .*:$' && section ==# 'staged'
|
2010-01-11 22:51:54 -05:00
|
|
|
return 'Git reset --patch'
|
2012-07-16 18:10:27 -04:00
|
|
|
elseif getline('.') =~# '^# .*:$' && section ==# 'unstaged'
|
2010-01-11 22:51:54 -05:00
|
|
|
return 'Git add --patch'
|
2012-07-16 18:10:27 -04:00
|
|
|
elseif getline('.') =~# '^# .*:$' && section ==# 'untracked'
|
|
|
|
return 'Git add -N .'
|
|
|
|
elseif filename ==# ''
|
2010-01-11 22:51:54 -05:00
|
|
|
continue
|
|
|
|
endif
|
|
|
|
if !exists('first_filename')
|
|
|
|
let first_filename = filename
|
|
|
|
endif
|
|
|
|
execute lnum
|
2012-07-16 18:10:27 -04:00
|
|
|
if filename =~ ' -> '
|
2010-01-11 22:51:54 -05:00
|
|
|
let reset += [split(filename,' -> ')[1]]
|
2012-07-16 11:16:35 -04:00
|
|
|
elseif section ==# 'staged'
|
2010-01-11 22:51:54 -05:00
|
|
|
let reset += [filename]
|
2012-07-16 18:10:27 -04:00
|
|
|
elseif getline(lnum) !~# '^#\tdeleted:'
|
2010-01-11 22:51:54 -05:00
|
|
|
let add += [filename]
|
|
|
|
endif
|
|
|
|
endfor
|
|
|
|
try
|
|
|
|
if !empty(add)
|
|
|
|
execute "Git add --patch -- ".join(map(add,'s:shellesc(v:val)'))
|
|
|
|
endif
|
|
|
|
if !empty(reset)
|
2015-03-29 16:29:18 -04:00
|
|
|
execute "Git reset --patch -- ".join(map(reset,'s:shellesc(v:val)'))
|
2010-01-11 22:51:54 -05:00
|
|
|
endif
|
|
|
|
if exists('first_filename')
|
|
|
|
silent! edit!
|
|
|
|
1
|
|
|
|
redraw
|
2012-07-28 11:54:52 -04:00
|
|
|
call search('^#\t\%([[:alpha:] ]\+: *\)\=\V'.first_filename.'\%( ([^()[:digit:]]\+)\)\=\$','W')
|
2010-01-11 22:51:54 -05:00
|
|
|
endif
|
|
|
|
catch /^fugitive:/
|
|
|
|
return 'echoerr v:errmsg'
|
|
|
|
endtry
|
|
|
|
return 'checktime'
|
|
|
|
endfunction
|
|
|
|
|
2014-06-21 08:48:11 -04:00
|
|
|
" Section: Gcommit
|
2010-01-09 23:31:22 -05:00
|
|
|
|
|
|
|
call s:command("-nargs=? -complete=customlist,s:CommitComplete Gcommit :execute s:Commit(<q-args>)")
|
|
|
|
|
2014-06-30 14:02:53 -04:00
|
|
|
function! s:Commit(args, ...) abort
|
|
|
|
let repo = a:0 ? a:1 : s:repo()
|
2012-03-03 10:08:00 -05:00
|
|
|
let cd = exists('*haslocaldir') && haslocaldir() ? 'lcd ' : 'cd '
|
|
|
|
let dir = getcwd()
|
2014-06-30 14:02:53 -04:00
|
|
|
let msgfile = repo.dir('COMMIT_EDITMSG')
|
2010-01-09 23:31:22 -05:00
|
|
|
let outfile = tempname()
|
|
|
|
let errorfile = tempname()
|
|
|
|
try
|
2012-03-03 03:22:48 -05:00
|
|
|
try
|
2014-06-30 14:02:53 -04:00
|
|
|
execute cd.s:fnameescape(repo.tree())
|
2014-06-21 11:11:17 -04:00
|
|
|
if s:winshell()
|
2012-03-03 03:22:48 -05:00
|
|
|
let command = ''
|
|
|
|
let old_editor = $GIT_EDITOR
|
|
|
|
let $GIT_EDITOR = 'false'
|
|
|
|
else
|
|
|
|
let command = 'env GIT_EDITOR=false '
|
|
|
|
endif
|
2014-06-30 14:02:53 -04:00
|
|
|
let command .= repo.git_command('commit').' '.a:args
|
2012-03-03 03:22:48 -05:00
|
|
|
if &shell =~# 'csh'
|
2013-03-12 02:32:13 -04:00
|
|
|
noautocmd silent execute '!('.command.' > '.outfile.') >& '.errorfile
|
2014-03-20 13:21:19 -04:00
|
|
|
elseif a:args =~# '\%(^\| \)-\%(-interactive\|p\|-patch\)\>'
|
2013-03-12 02:32:13 -04:00
|
|
|
noautocmd execute '!'.command.' 2> '.errorfile
|
2012-03-03 03:22:48 -05:00
|
|
|
else
|
2013-03-12 02:32:13 -04:00
|
|
|
noautocmd silent execute '!'.command.' > '.outfile.' 2> '.errorfile
|
2012-03-03 03:22:48 -05:00
|
|
|
endif
|
|
|
|
finally
|
|
|
|
execute cd.'`=dir`'
|
|
|
|
endtry
|
2011-05-09 20:05:50 -04:00
|
|
|
if !has('gui_running')
|
|
|
|
redraw!
|
2010-01-13 22:01:43 -05:00
|
|
|
endif
|
2010-01-09 23:31:22 -05:00
|
|
|
if !v:shell_error
|
|
|
|
if filereadable(outfile)
|
|
|
|
for line in readfile(outfile)
|
|
|
|
echo line
|
|
|
|
endfor
|
|
|
|
endif
|
|
|
|
return ''
|
|
|
|
else
|
2010-10-24 13:40:07 -04:00
|
|
|
let errors = readfile(errorfile)
|
|
|
|
let error = get(errors,-2,get(errors,-1,'!'))
|
2013-04-18 12:53:19 -04:00
|
|
|
if error =~# 'false''\=\.$'
|
2010-01-09 23:31:22 -05:00
|
|
|
let args = a:args
|
2014-07-05 18:58:18 -04:00
|
|
|
let args = s:gsub(args,'%(%(^| )-- )@<!%(^| )@<=%(-[esp]|--edit|--interactive|--patch|--signoff)%($| )','')
|
2014-06-21 11:19:59 -04:00
|
|
|
let args = s:gsub(args,'%(%(^| )-- )@<!%(^| )@<=%(-c|--reedit-message|--reuse-message|-F|--file|-m|--message)%(\s+|\=)%(''[^'']*''|"%(\\.|[^"])*"|\\.|\S)*','')
|
2010-01-09 23:31:22 -05:00
|
|
|
let args = s:gsub(args,'%(^| )@<=[%#]%(:\w)*','\=expand(submatch(0))')
|
2014-07-05 18:58:18 -04:00
|
|
|
let args = s:sub(args, '\ze -- |$', ' --no-edit --no-interactive --no-signoff')
|
2010-01-09 23:31:22 -05:00
|
|
|
let args = '-F '.s:shellesc(msgfile).' '.args
|
|
|
|
if args !~# '\%(^\| \)--cleanup\>'
|
|
|
|
let args = '--cleanup=strip '.args
|
|
|
|
endif
|
2010-02-07 21:54:07 -05:00
|
|
|
if bufname('%') == '' && line('$') == 1 && getline(1) == '' && !&mod
|
2011-12-06 15:57:45 -05:00
|
|
|
execute 'keepalt edit '.s:fnameescape(msgfile)
|
2014-06-29 14:52:43 -04:00
|
|
|
elseif a:args =~# '\%(^\| \)-\%(-verbose\|\w*v\)\>'
|
2015-06-29 17:52:39 -04:00
|
|
|
execute 'keepalt '.(tabpagenr()-1).'tabedit '.s:fnameescape(msgfile)
|
2011-09-05 20:46:52 -04:00
|
|
|
elseif s:buffer().type() ==# 'index'
|
2011-12-06 15:57:45 -05:00
|
|
|
execute 'keepalt edit '.s:fnameescape(msgfile)
|
2011-09-05 20:46:52 -04:00
|
|
|
execute (search('^#','n')+1).'wincmd+'
|
|
|
|
setlocal nopreviewwindow
|
2010-02-07 21:54:07 -05:00
|
|
|
else
|
2011-12-06 15:57:45 -05:00
|
|
|
execute 'keepalt split '.s:fnameescape(msgfile)
|
2010-02-07 21:54:07 -05:00
|
|
|
endif
|
2010-01-09 23:31:22 -05:00
|
|
|
let b:fugitive_commit_arguments = args
|
2012-03-03 03:22:48 -05:00
|
|
|
setlocal bufhidden=wipe filetype=gitcommit
|
2010-01-09 23:31:22 -05:00
|
|
|
return '1'
|
|
|
|
elseif error ==# '!'
|
|
|
|
return s:Status()
|
|
|
|
else
|
|
|
|
call s:throw(error)
|
|
|
|
endif
|
|
|
|
endif
|
|
|
|
catch /^fugitive:/
|
|
|
|
return 'echoerr v:errmsg'
|
|
|
|
finally
|
2010-01-13 22:01:43 -05:00
|
|
|
if exists('old_editor')
|
|
|
|
let $GIT_EDITOR = old_editor
|
|
|
|
endif
|
2010-01-09 23:31:22 -05:00
|
|
|
call delete(outfile)
|
|
|
|
call delete(errorfile)
|
|
|
|
call fugitive#reload_status()
|
|
|
|
endtry
|
|
|
|
endfunction
|
|
|
|
|
|
|
|
function! s:CommitComplete(A,L,P) abort
|
|
|
|
if a:A =~ '^-' || type(a:A) == type(0) " a:A is 0 on :Gcommit -<Tab>
|
|
|
|
let args = ['-C', '-F', '-a', '-c', '-e', '-i', '-m', '-n', '-o', '-q', '-s', '-t', '-u', '-v', '--all', '--allow-empty', '--amend', '--author=', '--cleanup=', '--dry-run', '--edit', '--file=', '--include', '--interactive', '--message=', '--no-verify', '--only', '--quiet', '--reedit-message=', '--reuse-message=', '--signoff', '--template=', '--untracked-files', '--verbose']
|
|
|
|
return filter(args,'v:val[0 : strlen(a:A)-1] ==# a:A')
|
|
|
|
else
|
|
|
|
return s:repo().superglob(a:A)
|
|
|
|
endif
|
|
|
|
endfunction
|
|
|
|
|
2014-03-27 17:22:35 -04:00
|
|
|
function! s:FinishCommit() abort
|
2010-01-09 23:31:22 -05:00
|
|
|
let args = getbufvar(+expand('<abuf>'),'fugitive_commit_arguments')
|
|
|
|
if !empty(args)
|
|
|
|
call setbufvar(+expand('<abuf>'),'fugitive_commit_arguments','')
|
2014-06-30 14:02:53 -04:00
|
|
|
return s:Commit(args, s:repo(getbufvar(+expand('<abuf>'),'git_dir')))
|
2010-01-09 23:31:22 -05:00
|
|
|
endif
|
|
|
|
return ''
|
|
|
|
endfunction
|
|
|
|
|
2014-06-25 13:05:14 -04:00
|
|
|
" Section: Gmerge, Gpull
|
|
|
|
|
|
|
|
call s:command("-nargs=? -bang -complete=custom,s:RevisionComplete Gmerge " .
|
|
|
|
\ "execute s:Merge('merge', <bang>0, <q-args>)")
|
|
|
|
call s:command("-nargs=? -bang -complete=custom,s:RemoteComplete Gpull " .
|
|
|
|
\ "execute s:Merge('pull --progress', <bang>0, <q-args>)")
|
|
|
|
|
|
|
|
function! s:RevisionComplete(A, L, P) abort
|
|
|
|
return s:repo().git_chomp('rev-parse', '--symbolic', '--branches', '--tags', '--remotes')
|
|
|
|
\ . "\nHEAD\nFETCH_HEAD\nORIG_HEAD"
|
|
|
|
endfunction
|
|
|
|
|
|
|
|
function! s:RemoteComplete(A, L, P) abort
|
|
|
|
let remote = matchstr(a:L, ' \zs\S\+\ze ')
|
|
|
|
if !empty(remote)
|
|
|
|
let matches = split(s:repo().git_chomp('ls-remote', remote), "\n")
|
|
|
|
call filter(matches, 'v:val =~# "\t" && v:val !~# "{"')
|
|
|
|
call map(matches, 's:sub(v:val, "^.*\t%(refs/%(heads/|tags/)=)=", "")')
|
|
|
|
else
|
|
|
|
let matches = split(s:repo().git_chomp('remote'), "\n")
|
|
|
|
endif
|
|
|
|
return join(matches, "\n")
|
|
|
|
endfunction
|
|
|
|
|
|
|
|
function! fugitive#cwindow() abort
|
|
|
|
if &buftype == 'quickfix'
|
|
|
|
cwindow
|
|
|
|
else
|
|
|
|
botright cwindow
|
|
|
|
if &buftype == 'quickfix'
|
|
|
|
wincmd p
|
|
|
|
endif
|
|
|
|
endif
|
|
|
|
endfunction
|
|
|
|
|
|
|
|
let s:common_efm = ''
|
|
|
|
\ . '%+Egit:%.%#,'
|
|
|
|
\ . '%+Eusage:%.%#,'
|
|
|
|
\ . '%+Eerror:%.%#,'
|
|
|
|
\ . '%+Efatal:%.%#,'
|
2014-06-29 14:46:16 -04:00
|
|
|
\ . '%-G%.%#%\e[K%.%#,'
|
2014-06-25 13:05:14 -04:00
|
|
|
\ . '%-G%.%#%\r%.%\+'
|
|
|
|
|
|
|
|
function! s:Merge(cmd, bang, args) abort
|
|
|
|
let cd = exists('*haslocaldir') && haslocaldir() ? 'lcd' : 'cd'
|
|
|
|
let cwd = getcwd()
|
|
|
|
let [mp, efm] = [&l:mp, &l:efm]
|
|
|
|
let had_merge_msg = filereadable(s:repo().dir('MERGE_MSG'))
|
|
|
|
try
|
|
|
|
let &l:errorformat = ''
|
|
|
|
\ . '%-Gerror:%.%#false''.,'
|
|
|
|
\ . '%-G%.%# ''git commit'' %.%#,'
|
|
|
|
\ . '%+Emerge:%.%#,'
|
|
|
|
\ . s:common_efm . ','
|
|
|
|
\ . '%+ECannot %.%#: You have unstaged changes.,'
|
|
|
|
\ . '%+ECannot %.%#: Your index contains uncommitted changes.,'
|
|
|
|
\ . '%+EThere is no tracking information for the current branch.,'
|
|
|
|
\ . '%+EYou are not currently on a branch. Please specify which,'
|
|
|
|
\ . 'CONFLICT (%m): %f deleted in %.%#,'
|
|
|
|
\ . 'CONFLICT (%m): Merge conflict in %f,'
|
|
|
|
\ . 'CONFLICT (%m): Rename \"%f\"->%.%#,'
|
|
|
|
\ . 'CONFLICT (%m): Rename %.%#->%f %.%#,'
|
|
|
|
\ . 'CONFLICT (%m): There is a directory with name %f in %.%#,'
|
|
|
|
\ . '%+ECONFLICT %.%#,'
|
|
|
|
\ . '%+EKONFLIKT %.%#,'
|
|
|
|
\ . '%+ECONFLIT %.%#,'
|
|
|
|
\ . "%+EXUNG \u0110\u1ed8T %.%#,"
|
|
|
|
\ . "%+E\u51b2\u7a81 %.%#,"
|
|
|
|
\ . 'U%\t%f'
|
|
|
|
if a:cmd =~# '^merge' && empty(a:args) &&
|
|
|
|
\ (had_merge_msg || isdirectory(s:repo().dir('rebase-apply')) ||
|
|
|
|
\ !empty(s:repo().git_chomp('diff-files', '--diff-filter=U')))
|
|
|
|
let &l:makeprg = g:fugitive_git_executable.' diff-files --name-status --diff-filter=U'
|
|
|
|
else
|
2015-05-19 11:12:13 -04:00
|
|
|
let &l:makeprg = s:sub(g:fugitive_git_executable . ' ' . a:cmd .
|
|
|
|
\ (a:args =~# ' \%(--no-edit\|--abort\|-m\)\>' ? '' : ' --edit') .
|
|
|
|
\ ' ' . a:args, ' *$', '')
|
2014-06-25 13:05:14 -04:00
|
|
|
endif
|
2015-05-19 11:12:13 -04:00
|
|
|
if !empty($GIT_EDITOR) || has('win32')
|
2014-06-25 13:05:14 -04:00
|
|
|
let old_editor = $GIT_EDITOR
|
|
|
|
let $GIT_EDITOR = 'false'
|
2015-05-19 11:12:13 -04:00
|
|
|
else
|
|
|
|
let &l:makeprg = 'env GIT_EDITOR=false ' . &l:makeprg
|
2014-06-25 13:05:14 -04:00
|
|
|
endif
|
|
|
|
execute cd fnameescape(s:repo().tree())
|
|
|
|
silent noautocmd make!
|
|
|
|
catch /^Vim\%((\a\+)\)\=:E211/
|
|
|
|
let err = v:exception
|
|
|
|
finally
|
|
|
|
redraw!
|
|
|
|
let [&l:mp, &l:efm] = [mp, efm]
|
|
|
|
if exists('old_editor')
|
|
|
|
let $GIT_EDITOR = old_editor
|
|
|
|
endif
|
|
|
|
execute cd fnameescape(cwd)
|
|
|
|
endtry
|
|
|
|
call fugitive#reload_status()
|
|
|
|
if empty(filter(getqflist(),'v:val.valid'))
|
|
|
|
if !had_merge_msg && filereadable(s:repo().dir('MERGE_MSG'))
|
|
|
|
cclose
|
2014-07-07 21:23:22 -04:00
|
|
|
return 'Gcommit --no-status -n -t '.s:shellesc(s:repo().dir('MERGE_MSG'))
|
2014-06-25 13:05:14 -04:00
|
|
|
endif
|
|
|
|
endif
|
|
|
|
let qflist = getqflist()
|
|
|
|
let found = 0
|
|
|
|
for e in qflist
|
|
|
|
if !empty(e.bufnr)
|
|
|
|
let found = 1
|
|
|
|
let e.pattern = '^<<<<<<<'
|
|
|
|
endif
|
|
|
|
endfor
|
|
|
|
call fugitive#cwindow()
|
|
|
|
if found
|
|
|
|
call setqflist(qflist, 'r')
|
|
|
|
if !a:bang
|
|
|
|
return 'cfirst'
|
|
|
|
endif
|
|
|
|
endif
|
|
|
|
return exists('err') ? 'echoerr '.string(err) : ''
|
|
|
|
endfunction
|
|
|
|
|
2014-06-21 08:48:11 -04:00
|
|
|
" Section: Ggrep, Glog
|
2009-10-10 19:47:14 -04:00
|
|
|
|
2009-12-14 00:00:03 -05:00
|
|
|
if !exists('g:fugitive_summary_format')
|
|
|
|
let g:fugitive_summary_format = '%s'
|
|
|
|
endif
|
|
|
|
|
2012-04-05 12:25:24 -04:00
|
|
|
call s:command("-bang -nargs=? -complete=customlist,s:EditComplete Ggrep :execute s:Grep('grep',<bang>0,<q-args>)")
|
|
|
|
call s:command("-bang -nargs=? -complete=customlist,s:EditComplete Glgrep :execute s:Grep('lgrep',<bang>0,<q-args>)")
|
2014-06-24 13:02:04 -04:00
|
|
|
call s:command("-bar -bang -nargs=* -range=0 -complete=customlist,s:EditComplete Glog :call s:Log('grep<bang>',<line1>,<count>,<f-args>)")
|
2014-09-02 12:05:34 -04:00
|
|
|
call s:command("-bar -bang -nargs=* -range=0 -complete=customlist,s:EditComplete Gllog :call s:Log('lgrep<bang>',<line1>,<count>,<f-args>)")
|
2009-10-10 19:47:14 -04:00
|
|
|
|
2012-04-05 12:25:24 -04:00
|
|
|
function! s:Grep(cmd,bang,arg) abort
|
2009-10-10 19:47:14 -04:00
|
|
|
let grepprg = &grepprg
|
|
|
|
let grepformat = &grepformat
|
|
|
|
let cd = exists('*haslocaldir') && haslocaldir() ? 'lcd ' : 'cd '
|
2010-01-13 17:50:18 -05:00
|
|
|
let dir = getcwd()
|
2009-10-10 19:47:14 -04:00
|
|
|
try
|
2010-01-13 17:50:18 -05:00
|
|
|
execute cd.'`=s:repo().tree()`'
|
2015-05-16 08:27:44 -04:00
|
|
|
let &grepprg = s:repo().git_command('--no-pager', 'grep', '-n', '--no-color')
|
2015-07-20 05:30:16 -04:00
|
|
|
let &grepformat = '%f:%l:%m,%f'
|
2012-04-05 12:25:24 -04:00
|
|
|
exe a:cmd.'! '.escape(matchstr(a:arg,'\v\C.{-}%($|[''" ]\@=\|)@='),'|')
|
|
|
|
let list = a:cmd =~# '^l' ? getloclist(0) : getqflist()
|
2009-10-10 19:47:14 -04:00
|
|
|
for entry in list
|
|
|
|
if bufname(entry.bufnr) =~ ':'
|
|
|
|
let entry.filename = s:repo().translate(bufname(entry.bufnr))
|
|
|
|
unlet! entry.bufnr
|
2014-06-19 16:40:26 -04:00
|
|
|
let changed = 1
|
2009-10-10 19:47:14 -04:00
|
|
|
elseif a:arg =~# '\%(^\| \)--cached\>'
|
|
|
|
let entry.filename = s:repo().translate(':0:'.bufname(entry.bufnr))
|
|
|
|
unlet! entry.bufnr
|
2014-06-19 16:40:26 -04:00
|
|
|
let changed = 1
|
2009-10-10 19:47:14 -04:00
|
|
|
endif
|
|
|
|
endfor
|
2014-06-19 16:40:26 -04:00
|
|
|
if a:cmd =~# '^l' && exists('changed')
|
2012-04-05 12:25:24 -04:00
|
|
|
call setloclist(0, list, 'r')
|
2014-06-19 16:40:26 -04:00
|
|
|
elseif exists('changed')
|
2012-04-07 18:16:54 -04:00
|
|
|
call setqflist(list, 'r')
|
2012-04-05 12:25:24 -04:00
|
|
|
endif
|
2009-10-10 19:47:14 -04:00
|
|
|
if !a:bang && !empty(list)
|
2012-04-05 12:25:24 -04:00
|
|
|
return (a:cmd =~# '^l' ? 'l' : 'c').'first'.matchstr(a:arg,'\v\C[''" ]\zs\|.*')
|
2009-10-14 18:57:11 -04:00
|
|
|
else
|
2010-03-19 19:59:08 -04:00
|
|
|
return matchstr(a:arg,'\v\C[''" ]\|\zs.*')
|
2009-10-10 19:47:14 -04:00
|
|
|
endif
|
|
|
|
finally
|
|
|
|
let &grepprg = grepprg
|
|
|
|
let &grepformat = grepformat
|
2010-01-13 17:50:18 -05:00
|
|
|
execute cd.'`=dir`'
|
2009-10-10 19:47:14 -04:00
|
|
|
endtry
|
|
|
|
endfunction
|
|
|
|
|
2014-06-24 13:02:04 -04:00
|
|
|
function! s:Log(cmd, line1, line2, ...) abort
|
2009-11-10 22:26:08 -05:00
|
|
|
let path = s:buffer().path('/')
|
2009-11-14 23:47:17 -05:00
|
|
|
if path =~# '^/\.git\%(/\|$\)' || index(a:000,'--') != -1
|
2009-11-10 22:26:08 -05:00
|
|
|
let path = ''
|
|
|
|
endif
|
2009-11-14 23:47:17 -05:00
|
|
|
let cmd = ['--no-pager', 'log', '--no-color']
|
2014-06-24 13:02:04 -04:00
|
|
|
let cmd += ['--pretty=format:fugitive://'.s:repo().dir().'//%H'.path.'::'.g:fugitive_summary_format]
|
2009-11-14 23:47:17 -05:00
|
|
|
if empty(filter(a:000[0 : index(a:000,'--')],'v:val !~# "^-"'))
|
|
|
|
if s:buffer().commit() =~# '\x\{40\}'
|
|
|
|
let cmd += [s:buffer().commit()]
|
|
|
|
elseif s:buffer().path() =~# '^\.git/refs/\|^\.git/.*HEAD$'
|
|
|
|
let cmd += [s:buffer().path()[5:-1]]
|
|
|
|
endif
|
|
|
|
end
|
|
|
|
let cmd += map(copy(a:000),'s:sub(v:val,"^\\%(%(:\\w)*)","\\=fnamemodify(s:buffer().path(),submatch(1))")')
|
2009-11-10 22:26:08 -05:00
|
|
|
if path =~# '/.'
|
2014-06-24 13:02:04 -04:00
|
|
|
if a:line2
|
|
|
|
let cmd += ['-L', a:line1 . ',' . a:line2 . ':' . path[1:-1]]
|
|
|
|
else
|
|
|
|
let cmd += ['--', path[1:-1]]
|
|
|
|
endif
|
2009-10-10 19:47:14 -04:00
|
|
|
endif
|
|
|
|
let grepformat = &grepformat
|
|
|
|
let grepprg = &grepprg
|
2009-11-14 23:47:17 -05:00
|
|
|
let cd = exists('*haslocaldir') && haslocaldir() ? 'lcd ' : 'cd '
|
2010-01-13 17:50:18 -05:00
|
|
|
let dir = getcwd()
|
2009-10-10 19:47:14 -04:00
|
|
|
try
|
2010-01-13 17:50:18 -05:00
|
|
|
execute cd.'`=s:repo().tree()`'
|
2012-11-04 17:28:25 -05:00
|
|
|
let &grepprg = escape(call(s:repo().git_command,cmd,s:repo()),'%#')
|
2014-06-24 13:02:04 -04:00
|
|
|
let &grepformat = '%Cdiff %.%#,%C--- %.%#,%C+++ %.%#,%Z@@ -%\d%\+\,%\d%\+ +%l\,%\d%\+ @@,%-G-%.%#,%-G+%.%#,%-G %.%#,%A%f::%m,%-G%.%#'
|
2009-10-10 19:47:14 -04:00
|
|
|
exe a:cmd
|
|
|
|
finally
|
|
|
|
let &grepformat = grepformat
|
|
|
|
let &grepprg = grepprg
|
2010-01-13 17:50:18 -05:00
|
|
|
execute cd.'`=dir`'
|
2009-10-10 19:47:14 -04:00
|
|
|
endtry
|
|
|
|
endfunction
|
|
|
|
|
2014-06-21 08:48:11 -04:00
|
|
|
" Section: Gedit, Gpedit, Gsplit, Gvsplit, Gtabedit, Gread
|
2009-10-10 19:47:14 -04:00
|
|
|
|
2011-08-19 02:43:31 -04:00
|
|
|
function! s:Edit(cmd,bang,...) abort
|
2012-09-21 12:30:28 -04:00
|
|
|
let buffer = s:buffer()
|
2011-08-19 02:40:34 -04:00
|
|
|
if a:cmd !~# 'read'
|
|
|
|
if &previewwindow && getbufvar('','fugitive_type') ==# 'index'
|
|
|
|
wincmd p
|
|
|
|
if &diff
|
|
|
|
let mywinnr = winnr()
|
|
|
|
for winnr in range(winnr('$'),1,-1)
|
|
|
|
if winnr != mywinnr && getwinvar(winnr,'&diff')
|
|
|
|
execute winnr.'wincmd w'
|
|
|
|
close
|
2014-06-21 14:19:13 -04:00
|
|
|
if winnr('$') > 1
|
|
|
|
wincmd p
|
|
|
|
endif
|
2011-08-19 02:40:34 -04:00
|
|
|
endif
|
|
|
|
endfor
|
|
|
|
endif
|
|
|
|
endif
|
|
|
|
endif
|
|
|
|
|
2011-08-19 02:43:31 -04:00
|
|
|
if a:bang
|
2014-02-28 21:48:21 -05:00
|
|
|
let arglist = map(copy(a:000), 's:gsub(v:val, ''\\@<!%(\\\\)*\zs[%#]'', ''\=s:buffer().expand(submatch(0))'')')
|
|
|
|
let args = join(arglist, ' ')
|
2011-08-19 02:43:31 -04:00
|
|
|
if a:cmd =~# 'read'
|
2012-09-21 12:30:28 -04:00
|
|
|
let git = buffer.repo().git_command()
|
2011-08-19 02:43:31 -04:00
|
|
|
let last = line('$')
|
|
|
|
silent call s:ExecuteInTree((a:cmd ==# 'read' ? '$read' : a:cmd).'!'.git.' --no-pager '.args)
|
|
|
|
if a:cmd ==# 'read'
|
|
|
|
silent execute '1,'.last.'delete_'
|
|
|
|
endif
|
|
|
|
call fugitive#reload_status()
|
|
|
|
diffupdate
|
|
|
|
return 'redraw|echo '.string(':!'.git.' '.args)
|
|
|
|
else
|
2011-10-07 01:32:46 -04:00
|
|
|
let temp = resolve(tempname())
|
2015-06-30 17:42:13 -04:00
|
|
|
let s:temp_files[s:cpath(temp)] = { 'dir': buffer.repo().dir(), 'args': arglist }
|
2011-08-19 02:43:31 -04:00
|
|
|
silent execute a:cmd.' '.temp
|
|
|
|
if a:cmd =~# 'pedit'
|
|
|
|
wincmd P
|
|
|
|
endif
|
|
|
|
let echo = s:Edit('read',1,args)
|
|
|
|
silent write!
|
2011-09-08 17:12:41 -04:00
|
|
|
setlocal buftype=nowrite nomodified filetype=git foldmarker=<<<<<<<,>>>>>>>
|
|
|
|
if getline(1) !~# '^diff '
|
|
|
|
setlocal readonly nomodifiable
|
|
|
|
endif
|
2011-08-19 02:43:31 -04:00
|
|
|
if a:cmd =~# 'pedit'
|
|
|
|
wincmd p
|
|
|
|
endif
|
|
|
|
return echo
|
|
|
|
endif
|
|
|
|
return ''
|
|
|
|
endif
|
|
|
|
|
2009-10-10 19:47:14 -04:00
|
|
|
if a:0 && a:1 == ''
|
|
|
|
return ''
|
|
|
|
elseif a:0
|
2013-02-10 12:57:37 -05:00
|
|
|
let file = buffer.expand(join(a:000, ' '))
|
2011-08-25 19:08:23 -04:00
|
|
|
elseif expand('%') ==# ''
|
|
|
|
let file = ':'
|
2012-09-21 12:30:28 -04:00
|
|
|
elseif buffer.commit() ==# '' && buffer.path('/') !~# '^/.git\>'
|
|
|
|
let file = buffer.path(':')
|
2009-10-10 19:47:14 -04:00
|
|
|
else
|
2012-09-21 12:30:28 -04:00
|
|
|
let file = buffer.path('/')
|
2009-10-10 19:47:14 -04:00
|
|
|
endif
|
2009-10-15 18:47:03 -04:00
|
|
|
try
|
2012-09-21 12:30:28 -04:00
|
|
|
let file = buffer.repo().translate(file)
|
2009-10-15 18:47:03 -04:00
|
|
|
catch /^fugitive:/
|
|
|
|
return 'echoerr v:errmsg'
|
|
|
|
endtry
|
2011-02-27 10:47:28 -05:00
|
|
|
if a:cmd ==# 'read'
|
2010-12-27 23:50:32 -05:00
|
|
|
return 'silent %delete_|read '.s:fnameescape(file).'|silent 1delete_|diffupdate|'.line('.')
|
2009-10-10 19:47:14 -04:00
|
|
|
else
|
|
|
|
return a:cmd.' '.s:fnameescape(file)
|
|
|
|
endif
|
|
|
|
endfunction
|
|
|
|
|
|
|
|
function! s:EditComplete(A,L,P) abort
|
2013-02-10 12:57:37 -05:00
|
|
|
return map(s:repo().superglob(a:A), 'fnameescape(v:val)')
|
2011-09-12 17:02:07 -04:00
|
|
|
endfunction
|
|
|
|
|
|
|
|
function! s:EditRunComplete(A,L,P) abort
|
2011-08-19 02:43:31 -04:00
|
|
|
if a:L =~# '^\w\+!'
|
|
|
|
return s:GitComplete(a:A,a:L,a:P)
|
|
|
|
else
|
|
|
|
return s:repo().superglob(a:A)
|
|
|
|
endif
|
2009-10-10 19:47:14 -04:00
|
|
|
endfunction
|
|
|
|
|
2013-02-10 12:57:37 -05:00
|
|
|
call s:command("-bar -bang -nargs=* -complete=customlist,s:EditComplete Ge :execute s:Edit('edit<bang>',0,<f-args>)")
|
|
|
|
call s:command("-bar -bang -nargs=* -complete=customlist,s:EditComplete Gedit :execute s:Edit('edit<bang>',0,<f-args>)")
|
|
|
|
call s:command("-bar -bang -nargs=* -complete=customlist,s:EditRunComplete Gpedit :execute s:Edit('pedit',<bang>0,<f-args>)")
|
|
|
|
call s:command("-bar -bang -nargs=* -complete=customlist,s:EditRunComplete Gsplit :execute s:Edit('split',<bang>0,<f-args>)")
|
|
|
|
call s:command("-bar -bang -nargs=* -complete=customlist,s:EditRunComplete Gvsplit :execute s:Edit('vsplit',<bang>0,<f-args>)")
|
|
|
|
call s:command("-bar -bang -nargs=* -complete=customlist,s:EditRunComplete Gtabedit :execute s:Edit('tabedit',<bang>0,<f-args>)")
|
|
|
|
call s:command("-bar -bang -nargs=* -count -complete=customlist,s:EditRunComplete Gread :execute s:Edit((!<count> && <line1> ? '' : <count>).'read',<bang>0,<f-args>)")
|
2009-10-10 19:47:14 -04:00
|
|
|
|
2014-06-21 08:48:11 -04:00
|
|
|
" Section: Gwrite, Gwq
|
2009-10-14 23:15:03 -04:00
|
|
|
|
2013-02-10 12:57:37 -05:00
|
|
|
call s:command("-bar -bang -nargs=* -complete=customlist,s:EditComplete Gwrite :execute s:Write(<bang>0,<f-args>)")
|
|
|
|
call s:command("-bar -bang -nargs=* -complete=customlist,s:EditComplete Gw :execute s:Write(<bang>0,<f-args>)")
|
|
|
|
call s:command("-bar -bang -nargs=* -complete=customlist,s:EditComplete Gwq :execute s:Wq(<bang>0,<f-args>)")
|
2009-10-14 23:15:03 -04:00
|
|
|
|
|
|
|
function! s:Write(force,...) abort
|
2010-01-09 23:31:22 -05:00
|
|
|
if exists('b:fugitive_commit_arguments')
|
|
|
|
return 'write|bdelete'
|
|
|
|
elseif expand('%:t') == 'COMMIT_EDITMSG' && $GIT_INDEX_FILE != ''
|
|
|
|
return 'wq'
|
2010-01-10 00:04:58 -05:00
|
|
|
elseif s:buffer().type() == 'index'
|
|
|
|
return 'Gcommit'
|
2011-09-08 17:12:41 -04:00
|
|
|
elseif s:buffer().path() ==# '' && getline(4) =~# '^+++ '
|
|
|
|
let filename = getline(4)[6:-1]
|
|
|
|
setlocal buftype=
|
|
|
|
silent write
|
|
|
|
setlocal buftype=nowrite
|
|
|
|
if matchstr(getline(2),'index [[:xdigit:]]\+\.\.\zs[[:xdigit:]]\{7\}') ==# s:repo().rev_parse(':0:'.filename)[0:6]
|
|
|
|
let err = s:repo().git_chomp('apply','--cached','--reverse',s:buffer().spec())
|
|
|
|
else
|
|
|
|
let err = s:repo().git_chomp('apply','--cached',s:buffer().spec())
|
|
|
|
endif
|
|
|
|
if err !=# ''
|
|
|
|
let v:errmsg = split(err,"\n")[0]
|
|
|
|
return 'echoerr v:errmsg'
|
|
|
|
elseif a:force
|
|
|
|
return 'bdelete'
|
|
|
|
else
|
|
|
|
return 'Gedit '.fnameescape(filename)
|
|
|
|
endif
|
2010-01-09 23:31:22 -05:00
|
|
|
endif
|
2009-10-14 23:15:03 -04:00
|
|
|
let mytab = tabpagenr()
|
|
|
|
let mybufnr = bufnr('')
|
2013-02-10 12:57:37 -05:00
|
|
|
let path = a:0 ? join(a:000, ' ') : s:buffer().path()
|
2009-10-14 23:15:03 -04:00
|
|
|
if path =~# '^:\d\>'
|
|
|
|
return 'write'.(a:force ? '! ' : ' ').s:fnameescape(s:repo().translate(s:buffer().expand(path)))
|
|
|
|
endif
|
|
|
|
let always_permitted = (s:buffer().path() ==# path && s:buffer().commit() =~# '^0\=$')
|
|
|
|
if !always_permitted && !a:force && s:repo().git_chomp_in_tree('diff','--name-status','HEAD','--',path) . s:repo().git_chomp_in_tree('ls-files','--others','--',path) !=# ''
|
|
|
|
let v:errmsg = 'fugitive: file has uncommitted changes (use ! to override)'
|
|
|
|
return 'echoerr v:errmsg'
|
|
|
|
endif
|
|
|
|
let file = s:repo().translate(path)
|
|
|
|
let treebufnr = 0
|
|
|
|
for nr in range(1,bufnr('$'))
|
2010-01-09 17:35:27 -05:00
|
|
|
if fnamemodify(bufname(nr),':p') ==# file
|
2009-10-14 23:15:03 -04:00
|
|
|
let treebufnr = nr
|
|
|
|
endif
|
|
|
|
endfor
|
|
|
|
|
|
|
|
if treebufnr > 0 && treebufnr != bufnr('')
|
|
|
|
let temp = tempname()
|
|
|
|
silent execute '%write '.temp
|
|
|
|
for tab in [mytab] + range(1,tabpagenr('$'))
|
|
|
|
for winnr in range(1,tabpagewinnr(tab,'$'))
|
|
|
|
if tabpagebuflist(tab)[winnr-1] == treebufnr
|
|
|
|
execute 'tabnext '.tab
|
2009-10-19 21:42:48 -04:00
|
|
|
if winnr != winnr()
|
|
|
|
execute winnr.'wincmd w'
|
|
|
|
let restorewinnr = 1
|
|
|
|
endif
|
2009-10-14 23:15:03 -04:00
|
|
|
try
|
|
|
|
let lnum = line('.')
|
|
|
|
let last = line('$')
|
|
|
|
silent execute '$read '.temp
|
|
|
|
silent execute '1,'.last.'delete_'
|
|
|
|
silent write!
|
|
|
|
silent execute lnum
|
|
|
|
let did = 1
|
|
|
|
finally
|
2009-10-19 21:42:48 -04:00
|
|
|
if exists('restorewinnr')
|
|
|
|
wincmd p
|
|
|
|
endif
|
2009-10-18 19:54:30 -04:00
|
|
|
execute 'tabnext '.mytab
|
2009-10-14 23:15:03 -04:00
|
|
|
endtry
|
|
|
|
endif
|
|
|
|
endfor
|
|
|
|
endfor
|
|
|
|
if !exists('did')
|
|
|
|
call writefile(readfile(temp,'b'),file,'b')
|
|
|
|
endif
|
|
|
|
else
|
|
|
|
execute 'write! '.s:fnameescape(s:repo().translate(path))
|
|
|
|
endif
|
|
|
|
|
2010-08-21 22:52:02 -04:00
|
|
|
if a:force
|
2014-06-22 12:27:26 -04:00
|
|
|
let error = s:repo().git_chomp_in_tree('add', '--force', '--', path)
|
2010-08-21 22:52:02 -04:00
|
|
|
else
|
2014-06-22 12:27:26 -04:00
|
|
|
let error = s:repo().git_chomp_in_tree('add', '--', path)
|
2010-08-21 22:52:02 -04:00
|
|
|
endif
|
2009-10-14 23:15:03 -04:00
|
|
|
if v:shell_error
|
|
|
|
let v:errmsg = 'fugitive: '.error
|
|
|
|
return 'echoerr v:errmsg'
|
|
|
|
endif
|
2010-01-09 17:35:27 -05:00
|
|
|
if s:buffer().path() ==# path && s:buffer().commit() =~# '^\d$'
|
2009-10-14 23:15:03 -04:00
|
|
|
set nomodified
|
|
|
|
endif
|
|
|
|
|
|
|
|
let one = s:repo().translate(':1:'.path)
|
|
|
|
let two = s:repo().translate(':2:'.path)
|
|
|
|
let three = s:repo().translate(':3:'.path)
|
|
|
|
for nr in range(1,bufnr('$'))
|
2012-04-01 22:04:10 -04:00
|
|
|
let name = fnamemodify(bufname(nr), ':p')
|
|
|
|
if bufloaded(nr) && !getbufvar(nr,'&modified') && (name ==# one || name ==# two || name ==# three)
|
2009-10-14 23:15:03 -04:00
|
|
|
execute nr.'bdelete'
|
|
|
|
endif
|
|
|
|
endfor
|
|
|
|
|
2009-10-19 21:42:48 -04:00
|
|
|
unlet! restorewinnr
|
2009-10-14 23:15:03 -04:00
|
|
|
let zero = s:repo().translate(':0:'.path)
|
|
|
|
for tab in range(1,tabpagenr('$'))
|
|
|
|
for winnr in range(1,tabpagewinnr(tab,'$'))
|
|
|
|
let bufnr = tabpagebuflist(tab)[winnr-1]
|
2012-04-01 22:04:10 -04:00
|
|
|
let bufname = fnamemodify(bufname(bufnr), ':p')
|
2009-10-14 23:15:03 -04:00
|
|
|
if bufname ==# zero && bufnr != mybufnr
|
|
|
|
execute 'tabnext '.tab
|
2009-10-19 21:42:48 -04:00
|
|
|
if winnr != winnr()
|
|
|
|
execute winnr.'wincmd w'
|
|
|
|
let restorewinnr = 1
|
|
|
|
endif
|
2009-10-14 23:15:03 -04:00
|
|
|
try
|
|
|
|
let lnum = line('.')
|
|
|
|
let last = line('$')
|
2012-04-03 18:42:58 -04:00
|
|
|
silent execute '$read '.s:fnameescape(file)
|
2009-10-14 23:15:03 -04:00
|
|
|
silent execute '1,'.last.'delete_'
|
|
|
|
silent execute lnum
|
|
|
|
set nomodified
|
|
|
|
diffupdate
|
|
|
|
finally
|
2009-10-19 21:42:48 -04:00
|
|
|
if exists('restorewinnr')
|
|
|
|
wincmd p
|
|
|
|
endif
|
2009-10-14 23:15:03 -04:00
|
|
|
execute 'tabnext '.mytab
|
|
|
|
endtry
|
|
|
|
break
|
|
|
|
endif
|
|
|
|
endfor
|
|
|
|
endfor
|
2009-11-03 22:23:58 -05:00
|
|
|
call fugitive#reload_status()
|
2009-10-14 23:15:03 -04:00
|
|
|
return 'checktime'
|
|
|
|
endfunction
|
|
|
|
|
2011-02-27 13:58:05 -05:00
|
|
|
function! s:Wq(force,...) abort
|
|
|
|
let bang = a:force ? '!' : ''
|
|
|
|
if exists('b:fugitive_commit_arguments')
|
|
|
|
return 'wq'.bang
|
|
|
|
endif
|
|
|
|
let result = call(s:function('s:Write'),[a:force]+a:000)
|
|
|
|
if result =~# '^\%(write\|wq\|echoerr\)'
|
|
|
|
return s:sub(result,'^write','wq')
|
|
|
|
else
|
|
|
|
return result.'|quit'.bang
|
|
|
|
endif
|
|
|
|
endfunction
|
|
|
|
|
2014-06-22 12:46:16 -04:00
|
|
|
augroup fugitive_commit
|
|
|
|
autocmd!
|
|
|
|
autocmd VimLeavePre,BufDelete COMMIT_EDITMSG execute s:sub(s:FinishCommit(), '^echoerr (.*)', 'echohl ErrorMsg|echo \1|echohl NONE')
|
|
|
|
augroup END
|
|
|
|
|
2014-06-30 14:30:44 -04:00
|
|
|
" Section: Gpush, Gfetch
|
|
|
|
|
|
|
|
call s:command("-nargs=? -bang -complete=custom,s:RemoteComplete Gpush execute s:Dispatch('<bang>', 'push '.<q-args>)")
|
|
|
|
call s:command("-nargs=? -bang -complete=custom,s:RemoteComplete Gfetch execute s:Dispatch('<bang>', 'fetch '.<q-args>)")
|
|
|
|
|
|
|
|
function! s:Dispatch(bang, args)
|
|
|
|
let cd = exists('*haslocaldir') && haslocaldir() ? 'lcd' : 'cd'
|
|
|
|
let cwd = getcwd()
|
|
|
|
let [mp, efm, cc] = [&l:mp, &l:efm, get(b:, 'current_compiler', '')]
|
|
|
|
try
|
|
|
|
let b:current_compiler = 'git'
|
|
|
|
let &l:errorformat = s:common_efm
|
|
|
|
let &l:makeprg = g:fugitive_git_executable . ' ' . a:args
|
|
|
|
execute cd fnameescape(s:repo().tree())
|
|
|
|
if exists(':Make') == 2
|
|
|
|
noautocmd Make
|
|
|
|
else
|
|
|
|
silent noautocmd make!
|
|
|
|
redraw!
|
|
|
|
return 'call fugitive#cwindow()'
|
|
|
|
endif
|
|
|
|
return ''
|
|
|
|
finally
|
|
|
|
let [&l:mp, &l:efm, b:current_compiler] = [mp, efm, cc]
|
|
|
|
if empty(cc) | unlet! b:current_compiler | endif
|
|
|
|
execute cd fnameescape(cwd)
|
|
|
|
endtry
|
|
|
|
endfunction
|
|
|
|
|
2014-06-21 08:48:11 -04:00
|
|
|
" Section: Gdiff
|
2009-10-10 19:47:14 -04:00
|
|
|
|
2014-06-23 20:06:24 -04:00
|
|
|
call s:command("-bang -bar -nargs=* -complete=customlist,s:EditComplete Gdiff :execute s:Diff('',<f-args>)")
|
2014-06-21 11:17:59 -04:00
|
|
|
call s:command("-bar -nargs=* -complete=customlist,s:EditComplete Gvdiff :execute s:Diff('keepalt vert ',<f-args>)")
|
2014-06-23 20:06:24 -04:00
|
|
|
call s:command("-bar -nargs=* -complete=customlist,s:EditComplete Gsdiff :execute s:Diff('keepalt ',<f-args>)")
|
2009-10-10 19:47:14 -04:00
|
|
|
|
2009-10-14 23:26:10 -04:00
|
|
|
augroup fugitive_diff
|
2010-05-25 15:32:35 -04:00
|
|
|
autocmd!
|
2014-05-30 14:26:40 -04:00
|
|
|
autocmd BufWinLeave *
|
2014-06-21 13:44:44 -04:00
|
|
|
\ if s:can_diffoff(+expand('<abuf>')) && s:diff_window_count() == 2 |
|
2014-05-30 14:26:40 -04:00
|
|
|
\ call s:diffoff_all(getbufvar(+expand('<abuf>'), 'git_dir')) |
|
|
|
|
\ endif
|
|
|
|
autocmd BufWinEnter *
|
2014-06-21 13:44:44 -04:00
|
|
|
\ if s:can_diffoff(+expand('<abuf>')) && s:diff_window_count() == 1 |
|
2014-05-30 14:26:40 -04:00
|
|
|
\ call s:diffoff() |
|
|
|
|
\ endif
|
2009-10-14 23:26:10 -04:00
|
|
|
augroup END
|
|
|
|
|
2014-06-21 13:44:44 -04:00
|
|
|
function! s:can_diffoff(buf) abort
|
|
|
|
return getwinvar(bufwinnr(a:buf), '&diff') &&
|
|
|
|
\ !empty(getbufvar(a:buf, 'git_dir')) &&
|
|
|
|
\ !empty(getwinvar(bufwinnr(a:buf), 'fugitive_diff_restore'))
|
|
|
|
endfunction
|
|
|
|
|
|
|
|
function! fugitive#can_diffoff(buf) abort
|
|
|
|
return s:can_diffoff(a:buf)
|
|
|
|
endfunction
|
|
|
|
|
2014-06-23 20:06:24 -04:00
|
|
|
function! s:diff_modifier(count) abort
|
2014-06-21 11:17:59 -04:00
|
|
|
let fdc = matchstr(&diffopt, 'foldcolumn:\zs\d\+')
|
2014-06-21 08:18:46 -04:00
|
|
|
if &diffopt =~# 'horizontal' && &diffopt !~# 'vertical'
|
2014-06-21 11:17:59 -04:00
|
|
|
return 'keepalt '
|
2014-06-23 20:06:24 -04:00
|
|
|
elseif &diffopt =~# 'vertical'
|
|
|
|
return 'keepalt vert '
|
2014-06-21 11:17:59 -04:00
|
|
|
elseif winwidth(0) <= a:count * ((&tw ? &tw : 80) + (empty(fdc) ? 2 : fdc))
|
|
|
|
return 'keepalt '
|
2014-06-21 08:18:46 -04:00
|
|
|
else
|
2014-06-21 11:17:59 -04:00
|
|
|
return 'keepalt vert '
|
2014-06-21 08:18:46 -04:00
|
|
|
endif
|
|
|
|
endfunction
|
|
|
|
|
2014-03-27 17:22:35 -04:00
|
|
|
function! s:diff_window_count() abort
|
2010-04-14 11:05:53 -04:00
|
|
|
let c = 0
|
|
|
|
for nr in range(1,winnr('$'))
|
|
|
|
let c += getwinvar(nr,'&diff')
|
|
|
|
endfor
|
|
|
|
return c
|
|
|
|
endfunction
|
|
|
|
|
2014-03-27 17:22:35 -04:00
|
|
|
function! s:diff_restore() abort
|
2013-04-19 15:53:02 -04:00
|
|
|
let restore = 'setlocal nodiff noscrollbind'
|
|
|
|
\ . ' scrollopt=' . &l:scrollopt
|
|
|
|
\ . (&l:wrap ? ' wrap' : ' nowrap')
|
2013-12-30 10:38:53 -05:00
|
|
|
\ . ' foldlevel=999'
|
2013-04-19 15:53:02 -04:00
|
|
|
\ . ' foldmethod=' . &l:foldmethod
|
|
|
|
\ . ' foldcolumn=' . &l:foldcolumn
|
|
|
|
\ . ' foldlevel=' . &l:foldlevel
|
2014-06-04 06:27:12 -04:00
|
|
|
\ . (&l:foldenable ? ' foldenable' : ' nofoldenable')
|
2013-04-19 15:53:02 -04:00
|
|
|
if has('cursorbind')
|
|
|
|
let restore .= (&l:cursorbind ? ' ' : ' no') . 'cursorbind'
|
|
|
|
endif
|
|
|
|
return restore
|
|
|
|
endfunction
|
|
|
|
|
2014-03-27 17:22:35 -04:00
|
|
|
function! s:diffthis() abort
|
2011-08-07 19:53:03 -04:00
|
|
|
if !&diff
|
2013-04-19 15:53:02 -04:00
|
|
|
let w:fugitive_diff_restore = s:diff_restore()
|
2011-08-07 19:53:03 -04:00
|
|
|
diffthis
|
|
|
|
endif
|
|
|
|
endfunction
|
|
|
|
|
2014-03-27 17:22:35 -04:00
|
|
|
function! s:diffoff() abort
|
2011-08-07 19:53:03 -04:00
|
|
|
if exists('w:fugitive_diff_restore')
|
|
|
|
execute w:fugitive_diff_restore
|
|
|
|
unlet w:fugitive_diff_restore
|
|
|
|
else
|
|
|
|
diffoff
|
|
|
|
endif
|
|
|
|
endfunction
|
|
|
|
|
2014-03-27 17:22:35 -04:00
|
|
|
function! s:diffoff_all(dir) abort
|
2014-12-10 22:03:08 -05:00
|
|
|
let curwin = winnr()
|
2010-11-13 20:04:34 -05:00
|
|
|
for nr in range(1,winnr('$'))
|
|
|
|
if getwinvar(nr,'&diff')
|
2010-11-13 20:15:26 -05:00
|
|
|
if nr != winnr()
|
|
|
|
execute nr.'wincmd w'
|
2010-11-13 20:04:34 -05:00
|
|
|
let restorewinnr = 1
|
|
|
|
endif
|
2010-11-13 20:26:53 -05:00
|
|
|
if exists('b:git_dir') && b:git_dir ==# a:dir
|
2011-08-07 19:53:03 -04:00
|
|
|
call s:diffoff()
|
2010-11-13 20:26:53 -05:00
|
|
|
endif
|
2010-11-13 20:04:34 -05:00
|
|
|
endif
|
|
|
|
endfor
|
2014-12-10 22:03:08 -05:00
|
|
|
execute curwin.'wincmd w'
|
2010-05-25 16:48:34 -04:00
|
|
|
endfunction
|
|
|
|
|
2010-01-30 00:31:10 -05:00
|
|
|
function! s:buffer_compare_age(commit) dict abort
|
|
|
|
let scores = {':0': 1, ':1': 2, ':2': 3, ':': 4, ':3': 5}
|
|
|
|
let my_score = get(scores,':'.self.commit(),0)
|
|
|
|
let their_score = get(scores,':'.a:commit,0)
|
|
|
|
if my_score || their_score
|
|
|
|
return my_score < their_score ? -1 : my_score != their_score
|
|
|
|
elseif self.commit() ==# a:commit
|
|
|
|
return 0
|
|
|
|
endif
|
|
|
|
let base = self.repo().git_chomp('merge-base',self.commit(),a:commit)
|
|
|
|
if base ==# self.commit()
|
|
|
|
return -1
|
|
|
|
elseif base ==# a:commit
|
|
|
|
return 1
|
|
|
|
endif
|
2010-01-30 00:38:00 -05:00
|
|
|
let my_time = +self.repo().git_chomp('log','--max-count=1','--pretty=format:%at',self.commit())
|
|
|
|
let their_time = +self.repo().git_chomp('log','--max-count=1','--pretty=format:%at',a:commit)
|
2010-01-30 00:31:10 -05:00
|
|
|
return my_time < their_time ? -1 : my_time != their_time
|
|
|
|
endfunction
|
|
|
|
|
|
|
|
call s:add_methods('buffer',['compare_age'])
|
|
|
|
|
2014-06-21 08:35:58 -04:00
|
|
|
function! s:Diff(vert,...) abort
|
2014-06-23 20:06:24 -04:00
|
|
|
let vert = empty(a:vert) ? s:diff_modifier(2) : a:vert
|
2009-10-10 19:47:14 -04:00
|
|
|
if exists(':DiffGitCached')
|
|
|
|
return 'DiffGitCached'
|
2009-10-14 23:26:10 -04:00
|
|
|
elseif (!a:0 || a:1 == ':') && s:buffer().commit() =~# '^[0-1]\=$' && s:repo().git_chomp_in_tree('ls-files', '--unmerged', '--', s:buffer().path()) !=# ''
|
2014-06-23 20:06:24 -04:00
|
|
|
let vert = empty(a:vert) ? s:diff_modifier(3) : a:vert
|
2011-04-25 11:50:19 -04:00
|
|
|
let nr = bufnr('')
|
2014-03-27 17:21:29 -04:00
|
|
|
execute 'leftabove '.vert.'split `=fugitive#buffer().repo().translate(s:buffer().expand('':2''))`'
|
2011-04-25 14:31:59 -04:00
|
|
|
execute 'nnoremap <buffer> <silent> dp :diffput '.nr.'<Bar>diffupdate<CR>'
|
2011-08-07 19:53:03 -04:00
|
|
|
call s:diffthis()
|
2010-05-25 16:32:09 -04:00
|
|
|
wincmd p
|
2014-03-27 17:21:29 -04:00
|
|
|
execute 'rightbelow '.vert.'split `=fugitive#buffer().repo().translate(s:buffer().expand('':3''))`'
|
2011-04-25 14:31:59 -04:00
|
|
|
execute 'nnoremap <buffer> <silent> dp :diffput '.nr.'<Bar>diffupdate<CR>'
|
2011-08-07 19:53:03 -04:00
|
|
|
call s:diffthis()
|
2010-05-25 16:32:09 -04:00
|
|
|
wincmd p
|
2011-08-07 19:53:03 -04:00
|
|
|
call s:diffthis()
|
2010-05-25 16:32:09 -04:00
|
|
|
return ''
|
2009-10-10 19:47:14 -04:00
|
|
|
elseif a:0
|
2013-02-10 12:57:37 -05:00
|
|
|
let arg = join(a:000, ' ')
|
|
|
|
if arg ==# ''
|
2009-10-10 19:47:14 -04:00
|
|
|
return ''
|
2013-02-10 12:57:37 -05:00
|
|
|
elseif arg ==# '/'
|
2009-10-14 23:26:10 -04:00
|
|
|
let file = s:buffer().path('/')
|
2013-02-10 12:57:37 -05:00
|
|
|
elseif arg ==# ':'
|
2009-10-14 23:26:10 -04:00
|
|
|
let file = s:buffer().path(':0:')
|
2013-02-10 12:57:37 -05:00
|
|
|
elseif arg =~# '^:/.'
|
2009-10-15 18:47:03 -04:00
|
|
|
try
|
2013-02-10 12:57:37 -05:00
|
|
|
let file = s:repo().rev_parse(arg).s:buffer().path(':')
|
2009-10-15 18:47:03 -04:00
|
|
|
catch /^fugitive:/
|
|
|
|
return 'echoerr v:errmsg'
|
|
|
|
endtry
|
2009-10-10 19:47:14 -04:00
|
|
|
else
|
2013-02-10 12:57:37 -05:00
|
|
|
let file = s:buffer().expand(arg)
|
2009-10-10 19:47:14 -04:00
|
|
|
endif
|
2010-02-14 15:55:09 -05:00
|
|
|
if file !~# ':' && file !~# '^/' && s:repo().git_chomp('cat-file','-t',file) =~# '^\%(tag\|commit\)$'
|
2009-10-15 18:33:08 -04:00
|
|
|
let file = file.s:buffer().path(':')
|
2009-10-10 19:47:14 -04:00
|
|
|
endif
|
|
|
|
else
|
2009-10-14 23:26:10 -04:00
|
|
|
let file = s:buffer().path(s:buffer().commit() == '' ? ':0:' : '/')
|
2009-10-10 19:47:14 -04:00
|
|
|
endif
|
|
|
|
try
|
2010-01-30 00:31:10 -05:00
|
|
|
let spec = s:repo().translate(file)
|
|
|
|
let commit = matchstr(spec,'\C[^:/]//\zs\x\+')
|
2013-12-30 10:45:54 -05:00
|
|
|
let restore = s:diff_restore()
|
2014-04-14 13:33:12 -04:00
|
|
|
if exists('+cursorbind')
|
|
|
|
setlocal cursorbind
|
|
|
|
endif
|
2013-12-30 10:45:54 -05:00
|
|
|
let w:fugitive_diff_restore = restore
|
2010-01-30 00:31:10 -05:00
|
|
|
if s:buffer().compare_age(commit) < 0
|
2013-12-30 10:45:54 -05:00
|
|
|
execute 'rightbelow '.vert.'diffsplit '.s:fnameescape(spec)
|
2010-01-30 00:31:10 -05:00
|
|
|
else
|
2013-12-30 10:45:54 -05:00
|
|
|
execute 'leftabove '.vert.'diffsplit '.s:fnameescape(spec)
|
2010-01-30 00:31:10 -05:00
|
|
|
endif
|
2013-12-30 10:45:54 -05:00
|
|
|
let w:fugitive_diff_restore = restore
|
2014-04-14 13:33:12 -04:00
|
|
|
let winnr = winnr()
|
|
|
|
if getwinvar('#', '&diff')
|
|
|
|
wincmd p
|
2015-01-25 19:16:31 -05:00
|
|
|
call feedkeys(winnr."\<C-W>w", 'n')
|
2014-04-14 13:33:12 -04:00
|
|
|
endif
|
2009-10-10 19:47:14 -04:00
|
|
|
return ''
|
|
|
|
catch /^fugitive:/
|
|
|
|
return 'echoerr v:errmsg'
|
|
|
|
endtry
|
|
|
|
endfunction
|
|
|
|
|
2014-06-21 08:48:11 -04:00
|
|
|
" Section: Gmove, Gremove
|
2009-10-10 19:47:14 -04:00
|
|
|
|
2014-03-27 17:22:35 -04:00
|
|
|
function! s:Move(force,destination) abort
|
2009-10-10 19:47:14 -04:00
|
|
|
if a:destination =~# '^/'
|
|
|
|
let destination = a:destination[1:-1]
|
|
|
|
else
|
2013-06-23 03:59:13 -04:00
|
|
|
let destination = s:shellslash(fnamemodify(s:sub(a:destination,'[%#]%(:\w)*','\=expand(submatch(0))'),':p'))
|
2010-01-09 17:35:27 -05:00
|
|
|
if destination[0:strlen(s:repo().tree())] ==# s:repo().tree('')
|
2009-10-10 19:47:14 -04:00
|
|
|
let destination = destination[strlen(s:repo().tree('')):-1]
|
|
|
|
endif
|
|
|
|
endif
|
2012-04-03 07:33:18 -04:00
|
|
|
if isdirectory(s:buffer().spec())
|
2011-01-04 15:04:47 -05:00
|
|
|
" Work around Vim parser idiosyncrasy
|
2011-04-25 15:14:32 -04:00
|
|
|
let discarded = s:buffer().setvar('&swapfile',0)
|
2010-12-27 23:27:03 -05:00
|
|
|
endif
|
2009-10-10 19:47:14 -04:00
|
|
|
let message = call(s:repo().git_chomp_in_tree,['mv']+(a:force ? ['-f'] : [])+['--', s:buffer().path(), destination], s:repo())
|
|
|
|
if v:shell_error
|
|
|
|
let v:errmsg = 'fugitive: '.message
|
|
|
|
return 'echoerr v:errmsg'
|
|
|
|
endif
|
|
|
|
let destination = s:repo().tree(destination)
|
|
|
|
if isdirectory(destination)
|
|
|
|
let destination = fnamemodify(s:sub(destination,'/$','').'/'.expand('%:t'),':.')
|
|
|
|
endif
|
2009-11-03 22:23:58 -05:00
|
|
|
call fugitive#reload_status()
|
2009-10-10 19:47:14 -04:00
|
|
|
if s:buffer().commit() == ''
|
2010-12-27 23:27:03 -05:00
|
|
|
if isdirectory(destination)
|
2012-03-13 20:58:59 -04:00
|
|
|
return 'keepalt edit '.s:fnameescape(destination)
|
2010-12-27 23:27:03 -05:00
|
|
|
else
|
2012-03-13 20:58:59 -04:00
|
|
|
return 'keepalt saveas! '.s:fnameescape(destination)
|
2010-12-27 23:27:03 -05:00
|
|
|
endif
|
2009-10-10 19:47:14 -04:00
|
|
|
else
|
2013-10-22 11:18:35 -04:00
|
|
|
return 'file '.s:fnameescape(s:repo().translate(':0:'.destination))
|
2009-10-10 19:47:14 -04:00
|
|
|
endif
|
|
|
|
endfunction
|
|
|
|
|
2014-03-27 17:22:35 -04:00
|
|
|
function! s:MoveComplete(A,L,P) abort
|
2009-10-10 19:47:14 -04:00
|
|
|
if a:A =~ '^/'
|
|
|
|
return s:repo().superglob(a:A)
|
|
|
|
else
|
2010-01-31 16:04:10 -05:00
|
|
|
let matches = split(glob(a:A.'*'),"\n")
|
|
|
|
call map(matches,'v:val !~ "/$" && isdirectory(v:val) ? v:val."/" : v:val')
|
|
|
|
return matches
|
2009-10-10 19:47:14 -04:00
|
|
|
endif
|
|
|
|
endfunction
|
|
|
|
|
2014-03-27 17:22:35 -04:00
|
|
|
function! s:Remove(force) abort
|
2009-10-10 19:47:14 -04:00
|
|
|
if s:buffer().commit() ==# ''
|
|
|
|
let cmd = ['rm']
|
|
|
|
elseif s:buffer().commit() ==# '0'
|
|
|
|
let cmd = ['rm','--cached']
|
|
|
|
else
|
|
|
|
let v:errmsg = 'fugitive: rm not supported here'
|
|
|
|
return 'echoerr v:errmsg'
|
|
|
|
endif
|
|
|
|
if a:force
|
|
|
|
let cmd += ['--force']
|
|
|
|
endif
|
|
|
|
let message = call(s:repo().git_chomp_in_tree,cmd+['--',s:buffer().path()],s:repo())
|
|
|
|
if v:shell_error
|
|
|
|
let v:errmsg = 'fugitive: '.s:sub(message,'error:.*\zs\n\(.*-f.*',' (add ! to force)')
|
|
|
|
return 'echoerr '.string(v:errmsg)
|
|
|
|
else
|
2009-11-03 22:23:58 -05:00
|
|
|
call fugitive#reload_status()
|
2015-05-19 12:27:22 -04:00
|
|
|
return 'edit'.(a:force ? '!' : '')
|
2009-10-10 19:47:14 -04:00
|
|
|
endif
|
|
|
|
endfunction
|
|
|
|
|
|
|
|
augroup fugitive_remove
|
|
|
|
autocmd!
|
|
|
|
autocmd User Fugitive if s:buffer().commit() =~# '^0\=$' |
|
|
|
|
\ exe "command! -buffer -bar -bang -nargs=1 -complete=customlist,s:MoveComplete Gmove :execute s:Move(<bang>0,<q-args>)" |
|
|
|
|
\ exe "command! -buffer -bar -bang Gremove :execute s:Remove(<bang>0)" |
|
|
|
|
\ endif
|
|
|
|
augroup END
|
|
|
|
|
2014-06-21 08:48:11 -04:00
|
|
|
" Section: Gblame
|
2009-10-10 19:47:14 -04:00
|
|
|
|
|
|
|
augroup fugitive_blame
|
|
|
|
autocmd!
|
|
|
|
autocmd BufReadPost *.fugitiveblame setfiletype fugitiveblame
|
|
|
|
autocmd FileType fugitiveblame setlocal nomodeline | if exists('b:git_dir') | let &l:keywordprg = s:repo().keywordprg() | endif
|
|
|
|
autocmd Syntax fugitiveblame call s:BlameSyntax()
|
2010-03-05 22:28:53 -05:00
|
|
|
autocmd User Fugitive if s:buffer().type('file', 'blob') | exe "command! -buffer -bar -bang -range=0 -nargs=* Gblame :execute s:Blame(<bang>0,<line1>,<line2>,<count>,[<f-args>])" | endif
|
2012-07-07 17:30:08 -04:00
|
|
|
autocmd ColorScheme,GUIEnter * call s:RehighlightBlame()
|
2009-10-10 19:47:14 -04:00
|
|
|
augroup END
|
|
|
|
|
2014-03-27 17:22:35 -04:00
|
|
|
function! s:linechars(pattern) abort
|
2012-10-09 14:33:06 -04:00
|
|
|
let chars = strlen(s:gsub(matchstr(getline('.'), a:pattern), '.', '.'))
|
|
|
|
if exists('*synconcealed') && &conceallevel > 1
|
|
|
|
for col in range(1, chars)
|
|
|
|
let chars -= synconcealed(line('.'), col)[0]
|
|
|
|
endfor
|
|
|
|
endif
|
|
|
|
return chars
|
2012-06-22 19:44:26 -04:00
|
|
|
endfunction
|
|
|
|
|
2010-03-05 22:28:53 -05:00
|
|
|
function! s:Blame(bang,line1,line2,count,args) abort
|
2014-06-26 14:40:09 -04:00
|
|
|
if exists('b:fugitive_blamed_bufnr')
|
|
|
|
return 'bdelete'
|
|
|
|
endif
|
2009-10-10 19:47:14 -04:00
|
|
|
try
|
|
|
|
if s:buffer().path() == ''
|
|
|
|
call s:throw('file or blob required')
|
|
|
|
endif
|
2012-10-09 16:24:31 -04:00
|
|
|
if filter(copy(a:args),'v:val !~# "^\\%(--root\|--show-name\\|-\\=\\%([ltfnsew]\\|[MC]\\d*\\)\\+\\)$"') != []
|
2010-03-05 22:28:53 -05:00
|
|
|
call s:throw('unsupported option')
|
|
|
|
endif
|
|
|
|
call map(a:args,'s:sub(v:val,"^\\ze[^-]","-")')
|
|
|
|
let cmd = ['--no-pager', 'blame', '--show-number'] + a:args
|
2009-11-11 00:16:02 -05:00
|
|
|
if s:buffer().commit() =~# '\D\|..'
|
2009-10-10 19:47:14 -04:00
|
|
|
let cmd += [s:buffer().commit()]
|
|
|
|
else
|
2009-10-12 21:48:16 -04:00
|
|
|
let cmd += ['--contents', '-']
|
2009-10-10 19:47:14 -04:00
|
|
|
endif
|
2014-02-28 21:48:21 -05:00
|
|
|
let cmd += ['--', s:buffer().path()]
|
|
|
|
let basecmd = escape(call(s:repo().git_command,cmd,s:repo()),'!')
|
2009-10-12 21:48:16 -04:00
|
|
|
try
|
|
|
|
let cd = exists('*haslocaldir') && haslocaldir() ? 'lcd ' : 'cd '
|
|
|
|
if !s:repo().bare()
|
|
|
|
let dir = getcwd()
|
2010-01-13 17:50:18 -05:00
|
|
|
execute cd.'`=s:repo().tree()`'
|
2009-10-10 19:47:14 -04:00
|
|
|
endif
|
2009-10-12 21:48:16 -04:00
|
|
|
if a:count
|
|
|
|
execute 'write !'.substitute(basecmd,' blame ',' blame -L '.a:line1.','.a:line2.' ','g')
|
|
|
|
else
|
2011-10-07 01:32:46 -04:00
|
|
|
let error = resolve(tempname())
|
2010-03-09 08:43:57 -05:00
|
|
|
let temp = error.'.fugitiveblame'
|
2010-06-08 11:08:05 -04:00
|
|
|
if &shell =~# 'csh'
|
|
|
|
silent! execute '%write !('.basecmd.' > '.temp.') >& '.error
|
|
|
|
else
|
|
|
|
silent! execute '%write !'.basecmd.' > '.temp.' 2> '.error
|
|
|
|
endif
|
2010-11-05 18:17:09 -04:00
|
|
|
if exists('l:dir')
|
|
|
|
execute cd.'`=dir`'
|
|
|
|
unlet dir
|
|
|
|
endif
|
2009-10-12 21:48:16 -04:00
|
|
|
if v:shell_error
|
2010-03-09 08:43:57 -05:00
|
|
|
call s:throw(join(readfile(error),"\n"))
|
2009-10-12 21:48:16 -04:00
|
|
|
endif
|
2011-10-04 03:13:46 -04:00
|
|
|
for winnr in range(winnr('$'),1,-1)
|
|
|
|
call setwinvar(winnr, '&scrollbind', 0)
|
2014-06-24 23:10:57 -04:00
|
|
|
if exists('+cursorbind')
|
|
|
|
call setwinvar(winnr, '&cursorbind', 0)
|
|
|
|
endif
|
2011-10-04 03:13:46 -04:00
|
|
|
if getbufvar(winbufnr(winnr), 'fugitive_blamed_bufnr')
|
|
|
|
execute winbufnr(winnr).'bdelete'
|
|
|
|
endif
|
|
|
|
endfor
|
2009-10-12 21:48:16 -04:00
|
|
|
let bufnr = bufnr('')
|
2010-05-25 15:34:53 -04:00
|
|
|
let restore = 'call setwinvar(bufwinnr('.bufnr.'),"&scrollbind",0)'
|
2014-06-24 23:10:57 -04:00
|
|
|
if exists('+cursorbind')
|
|
|
|
let restore .= '|call setwinvar(bufwinnr('.bufnr.'),"&cursorbind",0)'
|
|
|
|
endif
|
2009-10-12 21:48:16 -04:00
|
|
|
if &l:wrap
|
2010-05-25 15:34:53 -04:00
|
|
|
let restore .= '|call setwinvar(bufwinnr('.bufnr.'),"&wrap",1)'
|
2009-10-12 21:48:16 -04:00
|
|
|
endif
|
|
|
|
if &l:foldenable
|
2010-05-25 15:34:53 -04:00
|
|
|
let restore .= '|call setwinvar(bufwinnr('.bufnr.'),"&foldenable",1)'
|
2009-10-12 21:48:16 -04:00
|
|
|
endif
|
|
|
|
setlocal scrollbind nowrap nofoldenable
|
2014-06-24 23:10:57 -04:00
|
|
|
if exists('+cursorbind')
|
|
|
|
setlocal cursorbind
|
|
|
|
endif
|
2009-10-12 21:48:16 -04:00
|
|
|
let top = line('w0') + &scrolloff
|
|
|
|
let current = line('.')
|
2015-06-30 17:42:13 -04:00
|
|
|
let s:temp_files[s:cpath(temp)] = { 'dir': s:repo().dir(), 'args': cmd }
|
2012-01-24 11:45:36 -05:00
|
|
|
exe 'keepalt leftabove vsplit '.temp
|
2009-10-12 21:48:16 -04:00
|
|
|
let b:fugitive_blamed_bufnr = bufnr
|
2011-08-07 19:51:45 -04:00
|
|
|
let w:fugitive_leave = restore
|
2010-03-05 22:28:53 -05:00
|
|
|
let b:fugitive_blame_arguments = join(a:args,' ')
|
2009-10-12 21:48:16 -04:00
|
|
|
execute top
|
|
|
|
normal! zt
|
|
|
|
execute current
|
2014-06-24 23:10:57 -04:00
|
|
|
if exists('+cursorbind')
|
|
|
|
setlocal cursorbind
|
|
|
|
endif
|
2014-03-25 13:37:57 -04:00
|
|
|
setlocal nomodified nomodifiable nonumber scrollbind nowrap foldcolumn=0 nofoldenable winfixwidth filetype=fugitiveblame
|
2012-10-09 14:33:06 -04:00
|
|
|
if exists('+concealcursor')
|
|
|
|
setlocal concealcursor=nc conceallevel=2
|
|
|
|
endif
|
2011-08-25 14:51:48 -04:00
|
|
|
if exists('+relativenumber')
|
|
|
|
setlocal norelativenumber
|
|
|
|
endif
|
2012-10-09 14:33:06 -04:00
|
|
|
execute "vertical resize ".(s:linechars('.\{-\}\ze\s\+\d\+)')+1)
|
2014-04-07 05:00:22 -04:00
|
|
|
nnoremap <buffer> <silent> <F1> :help fugitive-:Gblame<CR>
|
|
|
|
nnoremap <buffer> <silent> g? :help fugitive-:Gblame<CR>
|
Return to correct window when closing Gblame window
Vim does not guarantee persistent window numbers. Instead, windows are
numbered according to their position on the screen, with the topmost,
leftmost window always having number 1, and the bottommost, rightmost
window always having a number equal to the total number of windows
currently visible. Crucially, this means that, when a window is closed,
windows which come "after" it in the positional order will be
renumbered.
When fugitive's Gblame window is closed, e.g. by pressing `q`, it
attempts to return focus to the window of the blamed buffer. Previously,
the number of the window to return to was computed before closing the
Gblame window, then the Gblame window was closed, then the blamed
buffer's window was focused. However, since windows were often
renumbered as soon as the Gblame window was closed, this would
frequently cause focus to jump to the window *after* the blamed buffer's
window, rather than the intended behavior.
This corrects the issue by jumping to the proper return window prior to
deleting the Gblame buffer, ensuring that the computed window number is
in fact correct at the moment when the focus change occurs.
2012-08-29 12:20:39 -04:00
|
|
|
nnoremap <buffer> <silent> q :exe substitute(bufwinnr(b:fugitive_blamed_bufnr).' wincmd w<Bar>'.bufnr('').'bdelete','^-1','','')<CR>
|
|
|
|
nnoremap <buffer> <silent> gq :exe substitute(bufwinnr(b:fugitive_blamed_bufnr).' wincmd w<Bar>'.bufnr('').'bdelete<Bar>if expand("%:p") =~# "^fugitive:[\\/][\\/]"<Bar>Gedit<Bar>endif','^-1','','')<CR>
|
2013-01-30 16:00:41 -05:00
|
|
|
nnoremap <buffer> <silent> <CR> :<C-U>exe <SID>BlameCommit("exe 'norm q'<Bar>edit")<CR>
|
2012-03-28 20:35:47 -04:00
|
|
|
nnoremap <buffer> <silent> - :<C-U>exe <SID>BlameJump('')<CR>
|
2010-01-15 13:37:00 -05:00
|
|
|
nnoremap <buffer> <silent> P :<C-U>exe <SID>BlameJump('^'.v:count1)<CR>
|
|
|
|
nnoremap <buffer> <silent> ~ :<C-U>exe <SID>BlameJump('~'.v:count1)<CR>
|
2011-10-01 17:25:18 -04:00
|
|
|
nnoremap <buffer> <silent> i :<C-U>exe <SID>BlameCommit("exe 'norm q'<Bar>edit")<CR>
|
|
|
|
nnoremap <buffer> <silent> o :<C-U>exe <SID>BlameCommit((&splitbelow ? "botright" : "topleft")." split")<CR>
|
|
|
|
nnoremap <buffer> <silent> O :<C-U>exe <SID>BlameCommit("tabedit")<CR>
|
2012-10-09 16:02:54 -04:00
|
|
|
nnoremap <buffer> <silent> A :<C-u>exe "vertical resize ".(<SID>linechars('.\{-\}\ze [0-9:/+-][0-9:/+ -]* \d\+)')+1+v:count)<CR>
|
|
|
|
nnoremap <buffer> <silent> C :<C-u>exe "vertical resize ".(<SID>linechars('^\S\+')+1+v:count)<CR>
|
|
|
|
nnoremap <buffer> <silent> D :<C-u>exe "vertical resize ".(<SID>linechars('.\{-\}\ze\d\ze\s\+\d\+)')+1-v:count)<CR>
|
2011-10-01 15:52:44 -04:00
|
|
|
redraw
|
2009-10-12 21:48:16 -04:00
|
|
|
syncbind
|
2009-10-10 19:47:14 -04:00
|
|
|
endif
|
2009-10-12 21:48:16 -04:00
|
|
|
finally
|
|
|
|
if exists('l:dir')
|
2010-01-13 17:50:18 -05:00
|
|
|
execute cd.'`=dir`'
|
2009-10-10 19:47:14 -04:00
|
|
|
endif
|
2009-10-12 21:48:16 -04:00
|
|
|
endtry
|
2009-10-10 19:47:14 -04:00
|
|
|
return ''
|
|
|
|
catch /^fugitive:/
|
|
|
|
return 'echoerr v:errmsg'
|
|
|
|
endtry
|
|
|
|
endfunction
|
|
|
|
|
2011-10-01 17:25:18 -04:00
|
|
|
function! s:BlameCommit(cmd) abort
|
|
|
|
let cmd = s:Edit(a:cmd, 0, matchstr(getline('.'),'\x\+'))
|
|
|
|
if cmd =~# '^echoerr'
|
|
|
|
return cmd
|
|
|
|
endif
|
|
|
|
let lnum = matchstr(getline('.'),' \zs\d\+\ze\s\+[([:digit:]]')
|
|
|
|
let path = matchstr(getline('.'),'^\^\=\x\+\s\+\zs.\{-\}\ze\s*\d\+ ')
|
|
|
|
if path ==# ''
|
|
|
|
let path = s:buffer(b:fugitive_blamed_bufnr).path()
|
|
|
|
endif
|
|
|
|
execute cmd
|
|
|
|
if search('^diff .* b/\M'.escape(path,'\').'$','W')
|
|
|
|
call search('^+++')
|
|
|
|
let head = line('.')
|
|
|
|
while search('^@@ \|^diff ') && getline('.') =~# '^@@ '
|
|
|
|
let top = +matchstr(getline('.'),' +\zs\d\+')
|
|
|
|
let len = +matchstr(getline('.'),' +\d\+,\zs\d\+')
|
|
|
|
if lnum >= top && lnum <= top + len
|
|
|
|
let offset = lnum - top
|
|
|
|
if &scrolloff
|
|
|
|
+
|
|
|
|
normal! zt
|
|
|
|
else
|
|
|
|
normal! zt
|
|
|
|
+
|
|
|
|
endif
|
|
|
|
while offset > 0 && line('.') < line('$')
|
|
|
|
+
|
|
|
|
if getline('.') =~# '^[ +]'
|
|
|
|
let offset -= 1
|
|
|
|
endif
|
|
|
|
endwhile
|
2014-06-10 18:46:04 -04:00
|
|
|
return 'normal! zv'
|
2011-10-01 17:25:18 -04:00
|
|
|
endif
|
|
|
|
endwhile
|
|
|
|
execute head
|
|
|
|
normal! zt
|
|
|
|
endif
|
|
|
|
return ''
|
|
|
|
endfunction
|
|
|
|
|
2010-01-15 13:37:00 -05:00
|
|
|
function! s:BlameJump(suffix) abort
|
2009-10-10 19:47:14 -04:00
|
|
|
let commit = matchstr(getline('.'),'^\^\=\zs\x\+')
|
|
|
|
if commit =~# '^0\+$'
|
|
|
|
let commit = ':0'
|
|
|
|
endif
|
2011-10-01 02:26:26 -04:00
|
|
|
let lnum = matchstr(getline('.'),' \zs\d\+\ze\s\+[([:digit:]]')
|
|
|
|
let path = matchstr(getline('.'),'^\^\=\x\+\s\+\zs.\{-\}\ze\s*\d\+ ')
|
2009-10-10 19:47:14 -04:00
|
|
|
if path ==# ''
|
|
|
|
let path = s:buffer(b:fugitive_blamed_bufnr).path()
|
|
|
|
endif
|
2010-03-05 22:28:53 -05:00
|
|
|
let args = b:fugitive_blame_arguments
|
2009-10-10 19:47:14 -04:00
|
|
|
let offset = line('.') - line('w0')
|
|
|
|
let bufnr = bufnr('%')
|
|
|
|
let winnr = bufwinnr(b:fugitive_blamed_bufnr)
|
|
|
|
if winnr > 0
|
|
|
|
exe winnr.'wincmd w'
|
|
|
|
endif
|
2011-08-21 15:53:12 -04:00
|
|
|
execute s:Edit('edit', 0, commit.a:suffix.':'.path)
|
2011-10-01 02:26:26 -04:00
|
|
|
execute lnum
|
2009-10-10 19:47:14 -04:00
|
|
|
if winnr > 0
|
|
|
|
exe bufnr.'bdelete'
|
|
|
|
endif
|
2010-03-05 22:28:53 -05:00
|
|
|
execute 'Gblame '.args
|
2009-10-10 19:47:14 -04:00
|
|
|
execute lnum
|
|
|
|
let delta = line('.') - line('w0') - offset
|
|
|
|
if delta > 0
|
2011-10-01 02:31:34 -04:00
|
|
|
execute 'normal! '.delta."\<C-E>"
|
2009-10-10 19:47:14 -04:00
|
|
|
elseif delta < 0
|
2011-10-01 02:31:34 -04:00
|
|
|
execute 'normal! '.(-delta)."\<C-Y>"
|
2009-10-10 19:47:14 -04:00
|
|
|
endif
|
|
|
|
syncbind
|
|
|
|
return ''
|
|
|
|
endfunction
|
|
|
|
|
2012-07-07 17:30:08 -04:00
|
|
|
let s:hash_colors = {}
|
|
|
|
|
2009-10-10 19:47:14 -04:00
|
|
|
function! s:BlameSyntax() abort
|
|
|
|
let b:current_syntax = 'fugitiveblame'
|
2012-10-09 14:33:06 -04:00
|
|
|
let conceal = has('conceal') ? ' conceal' : ''
|
|
|
|
let arg = exists('b:fugitive_blame_arguments') ? b:fugitive_blame_arguments : ''
|
2009-10-10 19:47:14 -04:00
|
|
|
syn match FugitiveblameBoundary "^\^"
|
2010-03-05 22:28:53 -05:00
|
|
|
syn match FugitiveblameBlank "^\s\+\s\@=" nextgroup=FugitiveblameAnnotation,fugitiveblameOriginalFile,FugitiveblameOriginalLineNumber skipwhite
|
|
|
|
syn match FugitiveblameHash "\%(^\^\=\)\@<=\x\{7,40\}\>" nextgroup=FugitiveblameAnnotation,FugitiveblameOriginalLineNumber,fugitiveblameOriginalFile skipwhite
|
2009-10-10 19:47:14 -04:00
|
|
|
syn match FugitiveblameUncommitted "\%(^\^\=\)\@<=0\{7,40\}\>" nextgroup=FugitiveblameAnnotation,FugitiveblameOriginalLineNumber,fugitiveblameOriginalFile skipwhite
|
|
|
|
syn region FugitiveblameAnnotation matchgroup=FugitiveblameDelimiter start="(" end="\%( \d\+\)\@<=)" contained keepend oneline
|
|
|
|
syn match FugitiveblameTime "[0-9:/+-][0-9:/+ -]*[0-9:/+-]\%( \+\d\+)\)\@=" contained containedin=FugitiveblameAnnotation
|
2012-10-09 14:33:06 -04:00
|
|
|
exec 'syn match FugitiveblameLineNumber " *\d\+)\@=" contained containedin=FugitiveblameAnnotation'.conceal
|
|
|
|
exec 'syn match FugitiveblameOriginalFile " \%(\f\+\D\@<=\|\D\@=\f\+\)\%(\%(\s\+\d\+\)\=\s\%((\|\s*\d\+)\)\)\@=" contained nextgroup=FugitiveblameOriginalLineNumber,FugitiveblameAnnotation skipwhite'.(arg =~# 'f' ? '' : conceal)
|
|
|
|
exec 'syn match FugitiveblameOriginalLineNumber " *\d\+\%(\s(\)\@=" contained nextgroup=FugitiveblameAnnotation skipwhite'.(arg =~# 'n' ? '' : conceal)
|
|
|
|
exec 'syn match FugitiveblameOriginalLineNumber " *\d\+\%(\s\+\d\+)\)\@=" contained nextgroup=FugitiveblameShort skipwhite'.(arg =~# 'n' ? '' : conceal)
|
|
|
|
syn match FugitiveblameShort " \d\+)" contained contains=FugitiveblameLineNumber
|
2009-10-10 19:47:14 -04:00
|
|
|
syn match FugitiveblameNotCommittedYet "(\@<=Not Committed Yet\>" contained containedin=FugitiveblameAnnotation
|
|
|
|
hi def link FugitiveblameBoundary Keyword
|
|
|
|
hi def link FugitiveblameHash Identifier
|
2012-07-07 17:30:08 -04:00
|
|
|
hi def link FugitiveblameUncommitted Ignore
|
2009-10-10 19:47:14 -04:00
|
|
|
hi def link FugitiveblameTime PreProc
|
|
|
|
hi def link FugitiveblameLineNumber Number
|
|
|
|
hi def link FugitiveblameOriginalFile String
|
|
|
|
hi def link FugitiveblameOriginalLineNumber Float
|
2010-03-05 22:28:53 -05:00
|
|
|
hi def link FugitiveblameShort FugitiveblameDelimiter
|
2009-10-10 19:47:14 -04:00
|
|
|
hi def link FugitiveblameDelimiter Delimiter
|
|
|
|
hi def link FugitiveblameNotCommittedYet Comment
|
2012-07-07 17:30:08 -04:00
|
|
|
let seen = {}
|
|
|
|
for lnum in range(1, line('$'))
|
|
|
|
let hash = matchstr(getline(lnum), '^\^\=\zs\x\{6\}')
|
|
|
|
if hash ==# '' || hash ==# '000000' || has_key(seen, hash)
|
|
|
|
continue
|
|
|
|
endif
|
|
|
|
let seen[hash] = 1
|
|
|
|
if &t_Co > 16 && exists('g:CSApprox_loaded')
|
|
|
|
\ && empty(get(s:hash_colors, hash))
|
|
|
|
let [s, r, g, b; __] = map(matchlist(hash, '\(\x\x\)\(\x\x\)\(\x\x\)'), 'str2nr(v:val,16)')
|
|
|
|
let color = csapprox#per_component#Approximate(r, g, b)
|
|
|
|
if color == 16 && &background ==# 'dark'
|
|
|
|
let color = 8
|
|
|
|
endif
|
|
|
|
let s:hash_colors[hash] = ' ctermfg='.color
|
|
|
|
else
|
|
|
|
let s:hash_colors[hash] = ''
|
|
|
|
endif
|
|
|
|
exe 'syn match FugitiveblameHash'.hash.' "\%(^\^\=\)\@<='.hash.'\x\{1,34\}\>" nextgroup=FugitiveblameAnnotation,FugitiveblameOriginalLineNumber,fugitiveblameOriginalFile skipwhite'
|
|
|
|
endfor
|
|
|
|
call s:RehighlightBlame()
|
|
|
|
endfunction
|
|
|
|
|
|
|
|
function! s:RehighlightBlame() abort
|
|
|
|
for [hash, cterm] in items(s:hash_colors)
|
|
|
|
if !empty(cterm) || has('gui_running')
|
|
|
|
exe 'hi FugitiveblameHash'.hash.' guifg=#'.hash.get(s:hash_colors, hash, '')
|
|
|
|
else
|
|
|
|
exe 'hi link FugitiveblameHash'.hash.' Identifier'
|
|
|
|
endif
|
|
|
|
endfor
|
2009-10-10 19:47:14 -04:00
|
|
|
endfunction
|
|
|
|
|
2014-06-21 08:48:11 -04:00
|
|
|
" Section: Gbrowse
|
2011-02-21 00:11:47 -05:00
|
|
|
|
2013-02-10 12:57:37 -05:00
|
|
|
call s:command("-bar -bang -range -nargs=* -complete=customlist,s:EditComplete Gbrowse :execute s:Browse(<bang>0,<line1>,<count>,<f-args>)")
|
2011-02-21 00:11:47 -05:00
|
|
|
|
|
|
|
function! s:Browse(bang,line1,count,...) abort
|
|
|
|
try
|
2013-02-10 12:57:37 -05:00
|
|
|
let rev = a:0 ? substitute(join(a:000, ' '),'@[[:alnum:]_-]*\%(://.\{-\}\)\=$','','') : ''
|
2011-02-26 15:40:59 -05:00
|
|
|
if rev ==# ''
|
|
|
|
let expanded = s:buffer().rev()
|
|
|
|
elseif rev ==# ':'
|
|
|
|
let expanded = s:buffer().path('/')
|
|
|
|
else
|
|
|
|
let expanded = s:buffer().expand(rev)
|
|
|
|
endif
|
|
|
|
let full = s:repo().translate(expanded)
|
|
|
|
let commit = ''
|
|
|
|
if full =~# '^fugitive://'
|
|
|
|
let commit = matchstr(full,'://.*//\zs\w\+')
|
|
|
|
let path = matchstr(full,'://.*//\w\+\zs/.*')
|
|
|
|
if commit =~ '..'
|
|
|
|
let type = s:repo().git_chomp('cat-file','-t',commit.s:sub(path,'^/',':'))
|
|
|
|
else
|
|
|
|
let type = 'blob'
|
|
|
|
endif
|
|
|
|
let path = path[1:-1]
|
|
|
|
elseif s:repo().bare()
|
|
|
|
let path = '.git/' . full[strlen(s:repo().dir())+1:-1]
|
|
|
|
let type = ''
|
|
|
|
else
|
|
|
|
let path = full[strlen(s:repo().tree())+1:-1]
|
|
|
|
if path =~# '^\.git/'
|
|
|
|
let type = ''
|
|
|
|
elseif isdirectory(full)
|
|
|
|
let type = 'tree'
|
|
|
|
else
|
|
|
|
let type = 'blob'
|
|
|
|
endif
|
|
|
|
endif
|
2011-02-26 20:55:04 -05:00
|
|
|
if path =~# '^\.git/.*HEAD' && filereadable(s:repo().dir(path[5:-1]))
|
|
|
|
let body = readfile(s:repo().dir(path[5:-1]))[0]
|
|
|
|
if body =~# '^\x\{40\}$'
|
|
|
|
let commit = body
|
|
|
|
let type = 'commit'
|
|
|
|
let path = ''
|
|
|
|
elseif body =~# '^ref: refs/'
|
|
|
|
let path = '.git/' . matchstr(body,'ref: \zs.*')
|
|
|
|
endif
|
|
|
|
endif
|
2011-02-26 15:40:59 -05:00
|
|
|
|
2013-02-10 12:57:37 -05:00
|
|
|
if a:0 && join(a:000, ' ') =~# '@[[:alnum:]_-]*\%(://.\{-\}\)\=$'
|
|
|
|
let remote = matchstr(join(a:000, ' '),'@\zs[[:alnum:]_-]\+\%(://.\{-\}\)\=$')
|
2011-02-26 15:40:59 -05:00
|
|
|
elseif path =~# '^\.git/refs/remotes/.'
|
|
|
|
let remote = matchstr(path,'^\.git/refs/remotes/\zs[^/]\+')
|
2011-02-21 00:11:47 -05:00
|
|
|
else
|
|
|
|
let remote = 'origin'
|
2011-02-26 15:40:59 -05:00
|
|
|
let branch = matchstr(rev,'^[[:alnum:]/._-]\+\ze[:^~@]')
|
2011-02-26 20:55:04 -05:00
|
|
|
if branch ==# '' && path =~# '^\.git/refs/\w\+/'
|
2011-02-26 15:40:59 -05:00
|
|
|
let branch = s:sub(path,'^\.git/refs/\w+/','')
|
|
|
|
endif
|
|
|
|
if filereadable(s:repo().dir('refs/remotes/'.branch))
|
|
|
|
let remote = matchstr(branch,'[^/]\+')
|
|
|
|
let rev = rev[strlen(remote)+1:-1]
|
|
|
|
else
|
|
|
|
if branch ==# ''
|
|
|
|
let branch = matchstr(s:repo().head_ref(),'\<refs/heads/\zs.*')
|
|
|
|
endif
|
|
|
|
if branch != ''
|
|
|
|
let remote = s:repo().git_chomp('config','branch.'.branch.'.remote')
|
2011-08-29 20:56:21 -04:00
|
|
|
if remote =~# '^\.\=$'
|
2011-02-26 15:40:59 -05:00
|
|
|
let remote = 'origin'
|
|
|
|
elseif rev[0:strlen(branch)-1] ==# branch && rev[strlen(branch)] =~# '[:^~@]'
|
|
|
|
let rev = s:repo().git_chomp('config','branch.'.branch.'.merge')[11:-1] . rev[strlen(branch):-1]
|
|
|
|
endif
|
2011-02-21 00:11:47 -05:00
|
|
|
endif
|
|
|
|
endif
|
|
|
|
endif
|
2011-02-26 15:40:59 -05:00
|
|
|
|
2011-02-21 00:11:47 -05:00
|
|
|
let raw = s:repo().git_chomp('config','remote.'.remote.'.url')
|
2011-02-24 15:51:51 -05:00
|
|
|
if raw ==# ''
|
|
|
|
let raw = remote
|
|
|
|
endif
|
2011-02-26 15:40:59 -05:00
|
|
|
|
2014-07-22 00:17:43 -04:00
|
|
|
for Handler in g:fugitive_browse_handlers
|
2014-07-22 20:45:54 -04:00
|
|
|
let url = call(Handler, [{
|
|
|
|
\ 'repo': s:repo(),
|
2014-07-22 00:17:43 -04:00
|
|
|
\ 'remote': raw,
|
|
|
|
\ 'revision': rev,
|
|
|
|
\ 'commit': commit,
|
|
|
|
\ 'path': path,
|
|
|
|
\ 'type': type,
|
2014-07-27 12:14:42 -04:00
|
|
|
\ 'line1': a:count > 0 ? a:line1 : 0,
|
|
|
|
\ 'line2': a:count > 0 ? a:count : 0}])
|
2014-07-17 20:16:28 -04:00
|
|
|
if !empty(url)
|
|
|
|
break
|
|
|
|
endif
|
|
|
|
endfor
|
2011-02-26 15:40:59 -05:00
|
|
|
|
2014-07-17 20:16:28 -04:00
|
|
|
if empty(url)
|
|
|
|
call s:throw("Instaweb failed to start and '".remote."' is not a supported remote")
|
2011-02-21 00:11:47 -05:00
|
|
|
endif
|
2011-02-26 15:40:59 -05:00
|
|
|
|
2011-02-21 00:11:47 -05:00
|
|
|
if a:bang
|
2014-07-23 07:42:26 -04:00
|
|
|
if has('clipboard')
|
|
|
|
let @* = url
|
|
|
|
endif
|
2011-02-21 00:11:47 -05:00
|
|
|
return 'echomsg '.string(url)
|
2014-06-26 17:07:07 -04:00
|
|
|
elseif exists(':Browse') == 2
|
2014-06-26 17:08:59 -04:00
|
|
|
return 'echomsg '.string(url).'|Browse '.url
|
2011-02-21 00:11:47 -05:00
|
|
|
else
|
2015-02-20 15:47:08 -05:00
|
|
|
if !exists('g:loaded_netrw')
|
|
|
|
runtime! autoload/netrw.vim
|
|
|
|
endif
|
|
|
|
if exists('*netrw#BrowseX')
|
2015-02-08 22:31:37 -05:00
|
|
|
return 'echomsg '.string(url).'|call netrw#BrowseX('.string(url).', 0)'
|
|
|
|
else
|
|
|
|
return 'echomsg '.string(url).'|call netrw#NetrwBrowseX('.string(url).', 0)'
|
|
|
|
endif
|
2011-02-21 00:11:47 -05:00
|
|
|
endif
|
|
|
|
catch /^fugitive:/
|
|
|
|
return 'echoerr v:errmsg'
|
|
|
|
endtry
|
|
|
|
endfunction
|
|
|
|
|
2014-07-22 20:45:54 -04:00
|
|
|
function! s:github_url(opts, ...) abort
|
2014-07-22 00:17:43 -04:00
|
|
|
if a:0 || type(a:opts) != type({})
|
|
|
|
return ''
|
|
|
|
endif
|
2012-03-14 16:27:46 -04:00
|
|
|
let domain_pattern = 'github\.com'
|
2012-11-18 22:43:04 -05:00
|
|
|
let domains = exists('g:fugitive_github_domains') ? g:fugitive_github_domains : []
|
|
|
|
for domain in domains
|
|
|
|
let domain_pattern .= '\|' . escape(split(domain, '://')[-1], '.')
|
2012-03-14 16:27:46 -04:00
|
|
|
endfor
|
2014-07-22 00:17:43 -04:00
|
|
|
let repo = matchstr(get(a:opts, 'remote'), '^\%(https\=://\|git://\|git@\)\=\zs\('.domain_pattern.'\)[/:].\{-\}\ze\%(\.git\)\=$')
|
2012-03-14 16:27:46 -04:00
|
|
|
if repo ==# ''
|
2011-02-21 00:11:47 -05:00
|
|
|
return ''
|
|
|
|
endif
|
2014-07-22 00:17:43 -04:00
|
|
|
let path = a:opts.path
|
2012-11-20 17:57:37 -05:00
|
|
|
if index(domains, 'http://' . matchstr(repo, '^[^:/]*')) >= 0
|
2012-11-18 22:43:04 -05:00
|
|
|
let root = 'http://' . s:sub(repo,':','/')
|
|
|
|
else
|
|
|
|
let root = 'https://' . s:sub(repo,':','/')
|
|
|
|
endif
|
2011-02-24 16:31:50 -05:00
|
|
|
if path =~# '^\.git/refs/heads/'
|
2014-07-22 20:45:54 -04:00
|
|
|
let branch = a:opts.repo.git_chomp('config','branch.'.path[16:-1].'.merge')[11:-1]
|
2011-02-24 16:31:50 -05:00
|
|
|
if branch ==# ''
|
2011-02-26 15:40:59 -05:00
|
|
|
return root . '/commits/' . path[16:-1]
|
2011-02-24 16:31:50 -05:00
|
|
|
else
|
2011-02-26 15:40:59 -05:00
|
|
|
return root . '/commits/' . branch
|
2011-02-24 16:31:50 -05:00
|
|
|
endif
|
|
|
|
elseif path =~# '^\.git/refs/.'
|
2011-02-26 15:40:59 -05:00
|
|
|
return root . '/commits/' . matchstr(path,'[^/]\+$')
|
|
|
|
elseif path =~# '.git/\%(config$\|hooks\>\)'
|
2011-02-21 00:11:47 -05:00
|
|
|
return root . '/admin'
|
|
|
|
elseif path =~# '^\.git\>'
|
|
|
|
return root
|
|
|
|
endif
|
2014-07-22 00:17:43 -04:00
|
|
|
if a:opts.revision =~# '^[[:alnum:]._-]\+:'
|
|
|
|
let commit = matchstr(a:opts.revision,'^[^:]*')
|
|
|
|
elseif a:opts.commit =~# '^\d\=$'
|
2014-07-22 20:45:54 -04:00
|
|
|
let local = matchstr(a:opts.repo.head_ref(),'\<refs/heads/\zs.*')
|
|
|
|
let commit = a:opts.repo.git_chomp('config','branch.'.local.'.merge')[11:-1]
|
2011-02-24 16:31:50 -05:00
|
|
|
if commit ==# ''
|
|
|
|
let commit = local
|
|
|
|
endif
|
2011-02-26 15:40:59 -05:00
|
|
|
else
|
2014-07-22 00:17:43 -04:00
|
|
|
let commit = a:opts.commit
|
2011-02-21 00:11:47 -05:00
|
|
|
endif
|
2014-07-22 00:17:43 -04:00
|
|
|
if a:opts.type == 'tree'
|
2011-02-21 00:11:47 -05:00
|
|
|
let url = s:sub(root . '/tree/' . commit . '/' . path,'/$','')
|
2014-07-22 00:17:43 -04:00
|
|
|
elseif a:opts.type == 'blob'
|
2011-02-21 00:11:47 -05:00
|
|
|
let url = root . '/blob/' . commit . '/' . path
|
2014-07-22 00:17:43 -04:00
|
|
|
if get(a:opts, 'line2') && a:opts.line1 == a:opts.line2
|
|
|
|
let url .= '#L' . a:opts.line1
|
|
|
|
elseif get(a:opts, 'line2')
|
2015-07-30 18:09:06 -04:00
|
|
|
let url .= '#L' . a:opts.line1 . '-L' . a:opts.line2
|
2011-02-21 00:11:47 -05:00
|
|
|
endif
|
2014-07-22 00:17:43 -04:00
|
|
|
elseif a:opts.type == 'tag'
|
2011-02-21 00:11:47 -05:00
|
|
|
let commit = matchstr(getline(3),'^tag \zs.*')
|
|
|
|
let url = root . '/tree/' . commit
|
|
|
|
else
|
|
|
|
let url = root . '/commit/' . commit
|
|
|
|
endif
|
|
|
|
return url
|
|
|
|
endfunction
|
|
|
|
|
2014-07-22 20:45:54 -04:00
|
|
|
function! s:instaweb_url(opts) abort
|
|
|
|
let output = a:opts.repo.git_chomp('instaweb','-b','unknown')
|
2011-02-21 00:11:47 -05:00
|
|
|
if output =~# 'http://'
|
2014-11-06 13:47:26 -05:00
|
|
|
let root = matchstr(output,'http://.*').'/?p='.fnamemodify(a:opts.repo.dir(),':t')
|
2011-02-21 00:11:47 -05:00
|
|
|
else
|
|
|
|
return ''
|
|
|
|
endif
|
2014-07-22 00:17:43 -04:00
|
|
|
if a:opts.path =~# '^\.git/refs/.'
|
|
|
|
return root . ';a=shortlog;h=' . matchstr(a:opts.path,'^\.git/\zs.*')
|
|
|
|
elseif a:opts.path =~# '^\.git\>'
|
2011-02-21 00:11:47 -05:00
|
|
|
return root
|
|
|
|
endif
|
|
|
|
let url = root
|
2014-07-22 00:17:43 -04:00
|
|
|
if a:opts.commit =~# '^\x\{40\}$'
|
|
|
|
if a:opts.type ==# 'commit'
|
2011-02-26 15:40:59 -05:00
|
|
|
let url .= ';a=commit'
|
|
|
|
endif
|
2014-07-22 20:45:54 -04:00
|
|
|
let url .= ';h=' . a:opts.repo.rev_parse(a:opts.commit . (a:opts.path == '' ? '' : ':' . a:opts.path))
|
2011-02-21 00:11:47 -05:00
|
|
|
else
|
2014-07-22 00:17:43 -04:00
|
|
|
if a:opts.type ==# 'blob'
|
2011-02-21 00:11:47 -05:00
|
|
|
let tmp = tempname()
|
2014-07-22 20:45:54 -04:00
|
|
|
silent execute 'write !'.a:opts.repo.git_command('hash-object','-w','--stdin').' > '.tmp
|
2011-02-21 00:11:47 -05:00
|
|
|
let url .= ';h=' . readfile(tmp)[0]
|
|
|
|
else
|
|
|
|
try
|
2014-07-22 20:45:54 -04:00
|
|
|
let url .= ';h=' . a:opts.repo.rev_parse((a:opts.commit == '' ? 'HEAD' : ':' . a:opts.commit) . ':' . a:opts.path)
|
2011-02-21 00:11:47 -05:00
|
|
|
catch /^fugitive:/
|
2011-02-26 20:12:34 -05:00
|
|
|
call s:throw('fugitive: cannot browse uncommitted file')
|
2011-02-21 00:11:47 -05:00
|
|
|
endtry
|
|
|
|
endif
|
2014-07-22 20:45:54 -04:00
|
|
|
let root .= ';hb=' . matchstr(a:opts.repo.head_ref(),'[^ ]\+$')
|
2011-02-21 00:11:47 -05:00
|
|
|
endif
|
2014-07-22 00:17:43 -04:00
|
|
|
if a:opts.path !=# ''
|
|
|
|
let url .= ';f=' . a:opts.path
|
2011-02-21 00:11:47 -05:00
|
|
|
endif
|
2014-07-22 00:17:43 -04:00
|
|
|
if get(a:opts, 'line1')
|
|
|
|
let url .= '#l' . a:opts.line1
|
2011-02-21 00:11:47 -05:00
|
|
|
endif
|
|
|
|
return url
|
|
|
|
endfunction
|
|
|
|
|
2014-07-22 00:17:43 -04:00
|
|
|
if !exists('g:fugitive_browse_handlers')
|
|
|
|
let g:fugitive_browse_handlers = []
|
2014-07-17 21:05:03 -04:00
|
|
|
endif
|
|
|
|
|
2014-07-22 00:17:43 -04:00
|
|
|
call extend(g:fugitive_browse_handlers,
|
2014-07-17 21:05:03 -04:00
|
|
|
\ [s:function('s:github_url'), s:function('s:instaweb_url')])
|
|
|
|
|
2014-06-21 08:48:11 -04:00
|
|
|
" Section: File access
|
2009-10-10 19:47:14 -04:00
|
|
|
|
2010-01-13 22:01:43 -05:00
|
|
|
function! s:ReplaceCmd(cmd,...) abort
|
2012-04-01 22:04:10 -04:00
|
|
|
let fn = expand('%:p')
|
2009-10-10 19:47:14 -04:00
|
|
|
let tmp = tempname()
|
2010-01-13 22:01:43 -05:00
|
|
|
let prefix = ''
|
2009-10-10 19:47:14 -04:00
|
|
|
try
|
2010-01-13 22:01:43 -05:00
|
|
|
if a:0 && a:1 != ''
|
2014-06-21 11:11:17 -04:00
|
|
|
if s:winshell()
|
2010-01-13 22:01:43 -05:00
|
|
|
let old_index = $GIT_INDEX_FILE
|
|
|
|
let $GIT_INDEX_FILE = a:1
|
|
|
|
else
|
2011-04-03 14:43:16 -04:00
|
|
|
let prefix = 'env GIT_INDEX_FILE='.s:shellesc(a:1).' '
|
2010-01-13 22:01:43 -05:00
|
|
|
endif
|
|
|
|
endif
|
2014-06-21 11:11:17 -04:00
|
|
|
if s:winshell()
|
2012-05-03 08:00:33 -04:00
|
|
|
let cmd_escape_char = &shellxquote == '(' ? '^' : '^^^'
|
|
|
|
call system('cmd /c "'.prefix.s:gsub(a:cmd,'[<>]', cmd_escape_char.'&').' > '.tmp.'"')
|
2011-08-09 00:59:38 -04:00
|
|
|
else
|
|
|
|
call system(' ('.prefix.a:cmd.' > '.tmp.') ')
|
|
|
|
endif
|
2009-10-10 19:47:14 -04:00
|
|
|
finally
|
2010-01-13 22:01:43 -05:00
|
|
|
if exists('old_index')
|
2010-03-09 19:13:28 -05:00
|
|
|
let $GIT_INDEX_FILE = old_index
|
2010-01-13 22:01:43 -05:00
|
|
|
endif
|
2009-10-10 19:47:14 -04:00
|
|
|
endtry
|
2014-06-22 19:36:43 -04:00
|
|
|
silent exe 'keepalt file '.tmp
|
2012-03-05 07:11:13 -05:00
|
|
|
try
|
|
|
|
silent edit!
|
|
|
|
finally
|
2014-04-09 22:55:34 -04:00
|
|
|
try
|
|
|
|
silent exe 'keepalt file '.s:fnameescape(fn)
|
|
|
|
catch /^Vim\%((\a\+)\)\=:E302/
|
|
|
|
endtry
|
2012-03-05 07:11:13 -05:00
|
|
|
call delete(tmp)
|
2012-04-01 22:04:10 -04:00
|
|
|
if fnamemodify(bufname('$'), ':p') ==# tmp
|
2012-03-05 07:11:13 -05:00
|
|
|
silent execute 'bwipeout '.bufnr('$')
|
|
|
|
endif
|
|
|
|
silent exe 'doau BufReadPost '.s:fnameescape(fn)
|
|
|
|
endtry
|
2009-10-10 19:47:14 -04:00
|
|
|
endfunction
|
|
|
|
|
2014-03-27 17:22:35 -04:00
|
|
|
function! s:BufReadIndex() abort
|
2009-10-19 22:11:40 -04:00
|
|
|
if !exists('b:fugitive_display_format')
|
2010-01-09 19:17:43 -05:00
|
|
|
let b:fugitive_display_format = filereadable(expand('%').'.lock')
|
2009-10-19 22:11:40 -04:00
|
|
|
endif
|
|
|
|
let b:fugitive_display_format = b:fugitive_display_format % 2
|
|
|
|
let b:fugitive_type = 'index'
|
2009-10-10 19:47:14 -04:00
|
|
|
try
|
|
|
|
let b:git_dir = s:repo().dir()
|
2012-03-05 06:58:00 -05:00
|
|
|
setlocal noro ma nomodeline
|
2010-01-09 19:17:43 -05:00
|
|
|
if fnamemodify($GIT_INDEX_FILE !=# '' ? $GIT_INDEX_FILE : b:git_dir . '/index', ':p') ==# expand('%:p')
|
2010-01-13 22:01:43 -05:00
|
|
|
let index = ''
|
2010-01-09 18:19:07 -05:00
|
|
|
else
|
2010-08-18 22:14:50 -04:00
|
|
|
let index = expand('%:p')
|
2010-01-09 18:19:07 -05:00
|
|
|
endif
|
2009-10-19 22:11:40 -04:00
|
|
|
if b:fugitive_display_format
|
2010-01-13 22:01:43 -05:00
|
|
|
call s:ReplaceCmd(s:repo().git_command('ls-files','--stage'),index)
|
2009-10-19 22:11:40 -04:00
|
|
|
set ft=git nospell
|
|
|
|
else
|
|
|
|
let cd = exists('*haslocaldir') && haslocaldir() ? 'lcd ' : 'cd '
|
|
|
|
let dir = getcwd()
|
2015-02-20 20:15:14 -05:00
|
|
|
if fugitive#git_version() =~# '^0\|^1\.[1-3]\.'
|
2013-10-24 00:16:15 -04:00
|
|
|
let cmd = s:repo().git_command('status')
|
2015-02-20 20:15:14 -05:00
|
|
|
elseif fugitive#git_version() =~# '^1\.[4-7]\.'
|
|
|
|
let cmd = s:repo().git_command('status', '-u')
|
2013-10-24 00:16:15 -04:00
|
|
|
else
|
|
|
|
let cmd = s:repo().git_command(
|
|
|
|
\ '-c', 'status.displayCommentPrefix=true',
|
|
|
|
\ '-c', 'color.status=false',
|
2014-06-03 15:47:05 -04:00
|
|
|
\ '-c', 'status.short=false',
|
2015-02-20 20:15:14 -05:00
|
|
|
\ '-c', 'status.showUntrackedFiles=all',
|
2013-10-24 00:16:15 -04:00
|
|
|
\ 'status')
|
|
|
|
endif
|
2009-10-19 22:11:40 -04:00
|
|
|
try
|
2010-01-13 17:50:18 -05:00
|
|
|
execute cd.'`=s:repo().tree()`'
|
2013-10-24 00:16:15 -04:00
|
|
|
call s:ReplaceCmd(cmd, index)
|
2009-10-19 22:11:40 -04:00
|
|
|
finally
|
2010-01-13 17:50:18 -05:00
|
|
|
execute cd.'`=dir`'
|
2009-10-19 22:11:40 -04:00
|
|
|
endtry
|
|
|
|
set ft=gitcommit
|
2013-01-13 16:01:17 -05:00
|
|
|
set foldtext=fugitive#foldtext()
|
2009-10-19 22:11:40 -04:00
|
|
|
endif
|
2012-03-12 18:36:16 -04:00
|
|
|
setlocal ro noma nomod noswapfile
|
|
|
|
if &bufhidden ==# ''
|
|
|
|
setlocal bufhidden=delete
|
|
|
|
endif
|
2011-08-19 15:01:37 -04:00
|
|
|
call s:JumpInit()
|
|
|
|
nunmap <buffer> P
|
|
|
|
nunmap <buffer> ~
|
2012-09-07 01:07:54 -04:00
|
|
|
nnoremap <buffer> <silent> <C-N> :<C-U>execute <SID>StageNext(v:count1)<CR>
|
|
|
|
nnoremap <buffer> <silent> <C-P> :<C-U>execute <SID>StagePrevious(v:count1)<CR>
|
2012-12-31 22:32:53 -05:00
|
|
|
nnoremap <buffer> <silent> - :<C-U>silent execute <SID>StageToggle(line('.'),line('.')+v:count1-1)<CR>
|
|
|
|
xnoremap <buffer> <silent> - :<C-U>silent execute <SID>StageToggle(line("'<"),line("'>"))<CR>
|
2009-10-19 22:11:40 -04:00
|
|
|
nnoremap <buffer> <silent> a :<C-U>let b:fugitive_display_format += 1<Bar>exe <SID>BufReadIndex()<CR>
|
|
|
|
nnoremap <buffer> <silent> i :<C-U>let b:fugitive_display_format -= 1<Bar>exe <SID>BufReadIndex()<CR>
|
2011-08-19 15:01:37 -04:00
|
|
|
nnoremap <buffer> <silent> C :<C-U>Gcommit<CR>
|
2011-08-25 15:45:00 -04:00
|
|
|
nnoremap <buffer> <silent> cA :<C-U>Gcommit --amend --reuse-message=HEAD<CR>
|
|
|
|
nnoremap <buffer> <silent> ca :<C-U>Gcommit --amend<CR>
|
2011-08-29 20:50:05 -04:00
|
|
|
nnoremap <buffer> <silent> cc :<C-U>Gcommit<CR>
|
2012-10-22 16:37:42 -04:00
|
|
|
nnoremap <buffer> <silent> cva :<C-U>Gcommit --amend --verbose<CR>
|
|
|
|
nnoremap <buffer> <silent> cvc :<C-U>Gcommit --verbose<CR>
|
2014-06-21 09:37:51 -04:00
|
|
|
nnoremap <buffer> <silent> D :<C-U>execute <SID>StageDiff('Gdiff')<CR>
|
|
|
|
nnoremap <buffer> <silent> dd :<C-U>execute <SID>StageDiff('Gdiff')<CR>
|
2011-02-27 13:14:58 -05:00
|
|
|
nnoremap <buffer> <silent> dh :<C-U>execute <SID>StageDiff('Gsdiff')<CR>
|
|
|
|
nnoremap <buffer> <silent> ds :<C-U>execute <SID>StageDiff('Gsdiff')<CR>
|
2011-08-19 15:13:44 -04:00
|
|
|
nnoremap <buffer> <silent> dp :<C-U>execute <SID>StageDiffEdit()<CR>
|
2011-08-19 15:01:37 -04:00
|
|
|
nnoremap <buffer> <silent> dv :<C-U>execute <SID>StageDiff('Gvdiff')<CR>
|
2010-01-11 22:51:54 -05:00
|
|
|
nnoremap <buffer> <silent> p :<C-U>execute <SID>StagePatch(line('.'),line('.')+v:count1-1)<CR>
|
|
|
|
xnoremap <buffer> <silent> p :<C-U>execute <SID>StagePatch(line("'<"),line("'>"))<CR>
|
2011-09-02 15:19:06 -04:00
|
|
|
nnoremap <buffer> <silent> q :<C-U>if bufnr('$') == 1<Bar>quit<Bar>else<Bar>bdelete<Bar>endif<CR>
|
2014-06-21 09:33:59 -04:00
|
|
|
nnoremap <buffer> <silent> r :<C-U>edit<CR>
|
2011-08-19 15:01:37 -04:00
|
|
|
nnoremap <buffer> <silent> R :<C-U>edit<CR>
|
2014-06-21 10:05:46 -04:00
|
|
|
nnoremap <buffer> <silent> U :<C-U>execute <SID>StageUndo()<CR>
|
2014-04-07 05:00:22 -04:00
|
|
|
nnoremap <buffer> <silent> g? :help fugitive-:Gstatus<CR>
|
2014-03-30 13:13:46 -04:00
|
|
|
nnoremap <buffer> <silent> <F1> :help fugitive-:Gstatus<CR>
|
2009-10-10 19:47:14 -04:00
|
|
|
catch /^fugitive:/
|
|
|
|
return 'echoerr v:errmsg'
|
|
|
|
endtry
|
|
|
|
endfunction
|
|
|
|
|
2014-03-27 17:22:35 -04:00
|
|
|
function! s:FileRead() abort
|
2009-10-10 19:47:14 -04:00
|
|
|
try
|
2012-03-18 22:44:04 -04:00
|
|
|
let repo = s:repo(fugitive#extract_git_dir(expand('<amatch>')))
|
2009-10-10 19:47:14 -04:00
|
|
|
let path = s:sub(s:sub(matchstr(expand('<amatch>'),'fugitive://.\{-\}//\zs.*'),'/',':'),'^\d:',':&')
|
|
|
|
let hash = repo.rev_parse(path)
|
|
|
|
if path =~ '^:'
|
|
|
|
let type = 'blob'
|
|
|
|
else
|
|
|
|
let type = repo.git_chomp('cat-file','-t',hash)
|
|
|
|
endif
|
|
|
|
" TODO: use count, if possible
|
|
|
|
return "read !".escape(repo.git_command('cat-file',type,hash),'%#\')
|
|
|
|
catch /^fugitive:/
|
|
|
|
return 'echoerr v:errmsg'
|
|
|
|
endtry
|
|
|
|
endfunction
|
|
|
|
|
2014-03-27 17:22:35 -04:00
|
|
|
function! s:BufReadIndexFile() abort
|
2009-10-10 19:47:14 -04:00
|
|
|
try
|
|
|
|
let b:fugitive_type = 'blob'
|
|
|
|
let b:git_dir = s:repo().dir()
|
2012-03-05 07:19:31 -05:00
|
|
|
try
|
|
|
|
call s:ReplaceCmd(s:repo().git_command('cat-file','blob',s:buffer().sha1()))
|
|
|
|
finally
|
|
|
|
if &bufhidden ==# ''
|
|
|
|
setlocal bufhidden=delete
|
|
|
|
endif
|
2014-03-19 00:53:05 -04:00
|
|
|
setlocal noswapfile
|
2012-03-05 07:19:31 -05:00
|
|
|
endtry
|
2009-10-10 19:47:14 -04:00
|
|
|
return ''
|
|
|
|
catch /^fugitive: rev-parse/
|
2012-04-01 22:04:10 -04:00
|
|
|
silent exe 'doau BufNewFile '.s:fnameescape(expand('%:p'))
|
2009-10-10 19:47:14 -04:00
|
|
|
return ''
|
|
|
|
catch /^fugitive:/
|
|
|
|
return 'echoerr v:errmsg'
|
|
|
|
endtry
|
|
|
|
endfunction
|
|
|
|
|
2014-03-27 17:22:35 -04:00
|
|
|
function! s:BufWriteIndexFile() abort
|
2009-10-10 19:47:14 -04:00
|
|
|
let tmp = tempname()
|
|
|
|
try
|
2009-10-14 22:30:36 -04:00
|
|
|
let path = matchstr(expand('<amatch>'),'//\d/\zs.*')
|
|
|
|
let stage = matchstr(expand('<amatch>'),'//\zs\d')
|
2009-10-10 19:47:14 -04:00
|
|
|
silent execute 'write !'.s:repo().git_command('hash-object','-w','--stdin').' > '.tmp
|
|
|
|
let sha1 = readfile(tmp)[0]
|
2009-10-14 22:30:36 -04:00
|
|
|
let old_mode = matchstr(s:repo().git_chomp('ls-files','--stage',path),'^\d\+')
|
2009-10-10 19:47:14 -04:00
|
|
|
if old_mode == ''
|
2009-10-14 22:30:36 -04:00
|
|
|
let old_mode = executable(s:repo().tree(path)) ? '100755' : '100644'
|
2009-10-10 19:47:14 -04:00
|
|
|
endif
|
2009-10-14 22:30:36 -04:00
|
|
|
let info = old_mode.' '.sha1.' '.stage."\t".path
|
2009-10-10 19:47:14 -04:00
|
|
|
call writefile([info],tmp)
|
2014-06-21 11:11:17 -04:00
|
|
|
if s:winshell()
|
2012-06-07 22:05:06 -04:00
|
|
|
let error = system('type '.s:gsub(tmp,'/','\\').'|'.s:repo().git_command('update-index','--index-info'))
|
2010-06-02 22:42:41 -04:00
|
|
|
else
|
|
|
|
let error = system(s:repo().git_command('update-index','--index-info').' < '.tmp)
|
|
|
|
endif
|
2009-10-10 19:47:14 -04:00
|
|
|
if v:shell_error == 0
|
|
|
|
setlocal nomodified
|
2014-11-20 15:43:36 -05:00
|
|
|
if exists('#BufWritePost')
|
|
|
|
execute 'doautocmd BufWritePost '.s:fnameescape(expand('%:p'))
|
|
|
|
endif
|
2009-11-03 22:23:58 -05:00
|
|
|
call fugitive#reload_status()
|
2009-10-10 19:47:14 -04:00
|
|
|
return ''
|
|
|
|
else
|
|
|
|
return 'echoerr '.string('fugitive: '.error)
|
|
|
|
endif
|
|
|
|
finally
|
|
|
|
call delete(tmp)
|
|
|
|
endtry
|
|
|
|
endfunction
|
|
|
|
|
2014-03-27 17:22:35 -04:00
|
|
|
function! s:BufReadObject() abort
|
2009-10-10 19:47:14 -04:00
|
|
|
try
|
|
|
|
setlocal noro ma
|
|
|
|
let b:git_dir = s:repo().dir()
|
|
|
|
let hash = s:buffer().sha1()
|
|
|
|
if !exists("b:fugitive_type")
|
|
|
|
let b:fugitive_type = s:repo().git_chomp('cat-file','-t',hash)
|
|
|
|
endif
|
|
|
|
if b:fugitive_type !~# '^\%(tag\|commit\|tree\|blob\)$'
|
2009-10-12 22:11:34 -04:00
|
|
|
return "echoerr 'fugitive: unrecognized git type'"
|
2009-10-10 19:47:14 -04:00
|
|
|
endif
|
|
|
|
let firstline = getline('.')
|
|
|
|
if !exists('b:fugitive_display_format') && b:fugitive_type != 'blob'
|
|
|
|
let b:fugitive_display_format = +getbufvar('#','fugitive_display_format')
|
|
|
|
endif
|
|
|
|
|
2012-03-05 06:58:00 -05:00
|
|
|
if b:fugitive_type !=# 'blob'
|
|
|
|
setlocal nomodeline
|
|
|
|
endif
|
|
|
|
|
2009-10-10 19:47:14 -04:00
|
|
|
let pos = getpos('.')
|
2014-03-19 23:36:20 -04:00
|
|
|
silent keepjumps %delete_
|
2009-10-10 19:47:14 -04:00
|
|
|
setlocal endofline
|
|
|
|
|
2012-03-05 07:19:31 -05:00
|
|
|
try
|
2012-03-05 07:32:01 -05:00
|
|
|
if b:fugitive_type ==# 'tree'
|
2012-03-05 07:19:31 -05:00
|
|
|
let b:fugitive_display_format = b:fugitive_display_format % 2
|
|
|
|
if b:fugitive_display_format
|
|
|
|
call s:ReplaceCmd(s:repo().git_command('ls-tree',hash))
|
|
|
|
else
|
|
|
|
call s:ReplaceCmd(s:repo().git_command('show','--no-color',hash))
|
|
|
|
endif
|
2012-03-05 07:32:01 -05:00
|
|
|
elseif b:fugitive_type ==# 'tag'
|
2012-03-05 07:19:31 -05:00
|
|
|
let b:fugitive_display_format = b:fugitive_display_format % 2
|
|
|
|
if b:fugitive_display_format
|
|
|
|
call s:ReplaceCmd(s:repo().git_command('cat-file',b:fugitive_type,hash))
|
|
|
|
else
|
|
|
|
call s:ReplaceCmd(s:repo().git_command('cat-file','-p',hash))
|
|
|
|
endif
|
2012-03-05 07:32:01 -05:00
|
|
|
elseif b:fugitive_type ==# 'commit'
|
2012-03-05 07:19:31 -05:00
|
|
|
let b:fugitive_display_format = b:fugitive_display_format % 2
|
|
|
|
if b:fugitive_display_format
|
|
|
|
call s:ReplaceCmd(s:repo().git_command('cat-file',b:fugitive_type,hash))
|
|
|
|
else
|
|
|
|
call s:ReplaceCmd(s:repo().git_command('show','--no-color','--pretty=format:tree %T%nparent %P%nauthor %an <%ae> %ad%ncommitter %cn <%ce> %cd%nencoding %e%n%n%s%n%n%b',hash))
|
2014-03-19 23:36:20 -04:00
|
|
|
keepjumps call search('^parent ')
|
2012-03-05 07:19:31 -05:00
|
|
|
if getline('.') ==# 'parent '
|
2014-03-19 23:36:20 -04:00
|
|
|
silent keepjumps delete_
|
2012-03-05 07:19:31 -05:00
|
|
|
else
|
2014-03-19 23:36:20 -04:00
|
|
|
silent keepjumps s/\%(^parent\)\@<! /\rparent /ge
|
2012-03-05 07:19:31 -05:00
|
|
|
endif
|
2014-03-19 23:36:20 -04:00
|
|
|
keepjumps let lnum = search('^encoding \%(<unknown>\)\=$','W',line('.')+3)
|
|
|
|
if lnum
|
|
|
|
silent keepjumps delete_
|
2012-03-05 07:19:31 -05:00
|
|
|
end
|
2014-03-19 23:36:20 -04:00
|
|
|
keepjumps 1
|
2012-03-05 07:19:31 -05:00
|
|
|
endif
|
|
|
|
elseif b:fugitive_type ==# 'blob'
|
2009-10-10 19:47:14 -04:00
|
|
|
call s:ReplaceCmd(s:repo().git_command('cat-file',b:fugitive_type,hash))
|
2014-04-02 02:32:20 -04:00
|
|
|
setlocal nomodeline
|
2009-10-10 19:47:14 -04:00
|
|
|
endif
|
2012-03-05 07:19:31 -05:00
|
|
|
finally
|
2014-03-19 23:36:20 -04:00
|
|
|
keepjumps call setpos('.',pos)
|
2014-03-19 00:53:05 -04:00
|
|
|
setlocal ro noma nomod noswapfile
|
2012-03-05 07:19:31 -05:00
|
|
|
if &bufhidden ==# ''
|
|
|
|
setlocal bufhidden=delete
|
|
|
|
endif
|
|
|
|
if b:fugitive_type !=# 'blob'
|
2014-06-21 10:25:30 -04:00
|
|
|
setlocal filetype=git foldmethod=syntax
|
2012-03-05 07:19:31 -05:00
|
|
|
nnoremap <buffer> <silent> a :<C-U>let b:fugitive_display_format += v:count1<Bar>exe <SID>BufReadObject()<CR>
|
|
|
|
nnoremap <buffer> <silent> i :<C-U>let b:fugitive_display_format -= v:count1<Bar>exe <SID>BufReadObject()<CR>
|
2009-10-10 19:47:14 -04:00
|
|
|
else
|
2012-03-05 07:19:31 -05:00
|
|
|
call s:JumpInit()
|
2009-10-10 19:47:14 -04:00
|
|
|
endif
|
2012-03-05 07:19:31 -05:00
|
|
|
endtry
|
2009-10-10 19:47:14 -04:00
|
|
|
|
|
|
|
return ''
|
|
|
|
catch /^fugitive:/
|
|
|
|
return 'echoerr v:errmsg'
|
|
|
|
endtry
|
|
|
|
endfunction
|
|
|
|
|
|
|
|
augroup fugitive_files
|
|
|
|
autocmd!
|
2012-03-16 22:27:45 -04:00
|
|
|
autocmd BufReadCmd index{,.lock}
|
2012-03-18 22:44:04 -04:00
|
|
|
\ if fugitive#is_git_dir(expand('<amatch>:p:h')) |
|
2012-03-16 22:27:45 -04:00
|
|
|
\ exe s:BufReadIndex() |
|
2012-08-01 10:35:52 -04:00
|
|
|
\ elseif filereadable(expand('<amatch>')) |
|
2012-07-08 01:11:12 -04:00
|
|
|
\ read <amatch> |
|
|
|
|
\ 1delete |
|
2012-03-16 22:27:45 -04:00
|
|
|
\ endif
|
2009-10-10 19:47:14 -04:00
|
|
|
autocmd FileReadCmd fugitive://**//[0-3]/** exe s:FileRead()
|
|
|
|
autocmd BufReadCmd fugitive://**//[0-3]/** exe s:BufReadIndexFile()
|
|
|
|
autocmd BufWriteCmd fugitive://**//[0-3]/** exe s:BufWriteIndexFile()
|
|
|
|
autocmd BufReadCmd fugitive://**//[0-9a-f][0-9a-f]* exe s:BufReadObject()
|
|
|
|
autocmd FileReadCmd fugitive://**//[0-9a-f][0-9a-f]* exe s:FileRead()
|
2012-07-15 13:33:36 -04:00
|
|
|
autocmd FileType git
|
|
|
|
\ if exists('b:git_dir') |
|
|
|
|
\ call s:JumpInit() |
|
|
|
|
\ endif
|
2009-10-10 19:47:14 -04:00
|
|
|
augroup END
|
|
|
|
|
2014-06-21 08:48:11 -04:00
|
|
|
" Section: Temp files
|
2011-08-19 02:21:33 -04:00
|
|
|
|
2011-10-07 01:32:46 -04:00
|
|
|
if !exists('s:temp_files')
|
|
|
|
let s:temp_files = {}
|
|
|
|
endif
|
2011-08-19 02:21:33 -04:00
|
|
|
|
|
|
|
augroup fugitive_temp
|
|
|
|
autocmd!
|
|
|
|
autocmd BufNewFile,BufReadPost *
|
2015-06-30 17:42:13 -04:00
|
|
|
\ if has_key(s:temp_files,s:cpath(expand('<afile>:p'))) |
|
|
|
|
\ let b:git_dir = s:temp_files[s:cpath(expand('<afile>:p'))].dir |
|
2011-08-19 02:21:33 -04:00
|
|
|
\ let b:git_type = 'temp' |
|
2015-06-30 17:42:13 -04:00
|
|
|
\ let b:git_args = s:temp_files[s:cpath(expand('<afile>:p'))].args |
|
2013-02-23 12:24:24 -05:00
|
|
|
\ call fugitive#detect(expand('<afile>:p')) |
|
2014-07-23 17:55:15 -04:00
|
|
|
\ setlocal bufhidden=delete nobuflisted |
|
2011-10-01 03:54:58 -04:00
|
|
|
\ nnoremap <buffer> <silent> q :<C-U>bdelete<CR>|
|
2011-08-19 02:21:33 -04:00
|
|
|
\ endif
|
|
|
|
augroup END
|
|
|
|
|
2014-06-21 08:48:11 -04:00
|
|
|
" Section: Go to file
|
2009-10-10 19:47:14 -04:00
|
|
|
|
|
|
|
function! s:JumpInit() abort
|
|
|
|
nnoremap <buffer> <silent> <CR> :<C-U>exe <SID>GF("edit")<CR>
|
|
|
|
if !&modifiable
|
|
|
|
nnoremap <buffer> <silent> o :<C-U>exe <SID>GF("split")<CR>
|
2012-03-26 00:02:08 -04:00
|
|
|
nnoremap <buffer> <silent> S :<C-U>exe <SID>GF("vsplit")<CR>
|
2009-10-10 19:47:14 -04:00
|
|
|
nnoremap <buffer> <silent> O :<C-U>exe <SID>GF("tabedit")<CR>
|
2013-03-12 02:01:49 -04:00
|
|
|
nnoremap <buffer> <silent> - :<C-U>exe <SID>Edit('edit',0,<SID>buffer().up(v:count1))<Bar> if fugitive#buffer().type('tree')<Bar>call search('^'.escape(expand('#:t'),'.*[]~\').'/\=$','wc')<Bar>endif<CR>
|
2011-08-21 15:53:12 -04:00
|
|
|
nnoremap <buffer> <silent> P :<C-U>exe <SID>Edit('edit',0,<SID>buffer().commit().'^'.v:count1.<SID>buffer().path(':'))<CR>
|
|
|
|
nnoremap <buffer> <silent> ~ :<C-U>exe <SID>Edit('edit',0,<SID>buffer().commit().'~'.v:count1.<SID>buffer().path(':'))<CR>
|
|
|
|
nnoremap <buffer> <silent> C :<C-U>exe <SID>Edit('edit',0,<SID>buffer().containing_commit())<CR>
|
|
|
|
nnoremap <buffer> <silent> cc :<C-U>exe <SID>Edit('edit',0,<SID>buffer().containing_commit())<CR>
|
|
|
|
nnoremap <buffer> <silent> co :<C-U>exe <SID>Edit('split',0,<SID>buffer().containing_commit())<CR>
|
2012-03-26 00:02:08 -04:00
|
|
|
nnoremap <buffer> <silent> cS :<C-U>exe <SID>Edit('vsplit',0,<SID>buffer().containing_commit())<CR>
|
2011-08-21 15:53:12 -04:00
|
|
|
nnoremap <buffer> <silent> cO :<C-U>exe <SID>Edit('tabedit',0,<SID>buffer().containing_commit())<CR>
|
2013-03-12 02:24:45 -04:00
|
|
|
nnoremap <buffer> <silent> cP :<C-U>exe <SID>Edit('pedit',0,<SID>buffer().containing_commit())<CR>
|
2013-03-12 02:22:02 -04:00
|
|
|
nnoremap <buffer> . : <C-R>=fnameescape(<SID>recall())<CR><Home>
|
2009-10-10 19:47:14 -04:00
|
|
|
endif
|
|
|
|
endfunction
|
|
|
|
|
|
|
|
function! s:GF(mode) abort
|
|
|
|
try
|
|
|
|
let buffer = s:buffer()
|
|
|
|
let myhash = buffer.sha1()
|
2011-08-19 02:43:31 -04:00
|
|
|
if myhash ==# '' && getline(1) =~# '^\%(commit\|tag\) \w'
|
|
|
|
let myhash = matchstr(getline(1),'^\w\+ \zs\S\+')
|
|
|
|
endif
|
2009-10-10 19:47:14 -04:00
|
|
|
|
2009-10-19 22:11:40 -04:00
|
|
|
if buffer.type('tree')
|
2009-10-10 19:47:14 -04:00
|
|
|
let showtree = (getline(1) =~# '^tree ' && getline(2) == "")
|
|
|
|
if showtree && line('.') == 1
|
|
|
|
return ""
|
|
|
|
elseif showtree && line('.') > 2
|
2011-08-19 02:43:31 -04:00
|
|
|
return s:Edit(a:mode,0,buffer.commit().':'.s:buffer().path().(buffer.path() =~# '^$\|/$' ? '' : '/').s:sub(getline('.'),'/$',''))
|
2009-10-10 19:47:14 -04:00
|
|
|
elseif getline('.') =~# '^\d\{6\} \l\{3,8\} \x\{40\}\t'
|
2011-08-19 02:43:31 -04:00
|
|
|
return s:Edit(a:mode,0,buffer.commit().':'.s:buffer().path().(buffer.path() =~# '^$\|/$' ? '' : '/').s:sub(matchstr(getline('.'),'\t\zs.*'),'/$',''))
|
2009-10-10 19:47:14 -04:00
|
|
|
endif
|
|
|
|
|
|
|
|
elseif buffer.type('blob')
|
|
|
|
let ref = expand("<cfile>")
|
|
|
|
try
|
|
|
|
let sha1 = buffer.repo().rev_parse(ref)
|
|
|
|
catch /^fugitive:/
|
|
|
|
endtry
|
|
|
|
if exists('sha1')
|
2011-08-19 02:43:31 -04:00
|
|
|
return s:Edit(a:mode,0,ref)
|
2009-10-10 19:47:14 -04:00
|
|
|
endif
|
|
|
|
|
|
|
|
else
|
2009-10-19 22:11:40 -04:00
|
|
|
|
|
|
|
" Index
|
|
|
|
if getline('.') =~# '^\d\{6\} \x\{40\} \d\t'
|
|
|
|
let ref = matchstr(getline('.'),'\x\{40\}')
|
|
|
|
let file = ':'.s:sub(matchstr(getline('.'),'\d\t.*'),'\t',':')
|
2011-08-19 02:43:31 -04:00
|
|
|
return s:Edit(a:mode,0,file)
|
2009-10-19 22:11:40 -04:00
|
|
|
|
|
|
|
elseif getline('.') =~# '^#\trenamed:.* -> '
|
|
|
|
let file = '/'.matchstr(getline('.'),' -> \zs.*')
|
2011-08-19 02:43:31 -04:00
|
|
|
return s:Edit(a:mode,0,file)
|
2009-10-19 22:11:40 -04:00
|
|
|
elseif getline('.') =~# '^#\t[[:alpha:] ]\+: *.'
|
2012-07-28 11:54:52 -04:00
|
|
|
let file = '/'.matchstr(getline('.'),': *\zs.\{-\}\ze\%( ([^()[:digit:]]\+)\)\=$')
|
2011-08-19 02:43:31 -04:00
|
|
|
return s:Edit(a:mode,0,file)
|
2009-10-19 22:11:40 -04:00
|
|
|
elseif getline('.') =~# '^#\t.'
|
|
|
|
let file = '/'.matchstr(getline('.'),'#\t\zs.*')
|
2011-08-19 02:43:31 -04:00
|
|
|
return s:Edit(a:mode,0,file)
|
2009-10-19 22:11:40 -04:00
|
|
|
elseif getline('.') =~# ': needs merge$'
|
|
|
|
let file = '/'.matchstr(getline('.'),'.*\ze: needs merge$')
|
2011-08-19 02:43:31 -04:00
|
|
|
return s:Edit(a:mode,0,file).'|Gdiff'
|
2009-10-19 22:11:40 -04:00
|
|
|
|
|
|
|
elseif getline('.') ==# '# Not currently on any branch.'
|
2011-08-19 02:43:31 -04:00
|
|
|
return s:Edit(a:mode,0,'HEAD')
|
2009-10-19 22:11:40 -04:00
|
|
|
elseif getline('.') =~# '^# On branch '
|
|
|
|
let file = 'refs/heads/'.getline('.')[12:]
|
2011-08-19 02:43:31 -04:00
|
|
|
return s:Edit(a:mode,0,file)
|
2009-10-19 22:11:40 -04:00
|
|
|
elseif getline('.') =~# "^# Your branch .*'"
|
2010-01-09 23:20:30 -05:00
|
|
|
let file = matchstr(getline('.'),"'\\zs\\S\\+\\ze'")
|
2011-08-19 02:43:31 -04:00
|
|
|
return s:Edit(a:mode,0,file)
|
2009-10-19 22:11:40 -04:00
|
|
|
endif
|
|
|
|
|
2009-10-10 19:47:14 -04:00
|
|
|
let showtree = (getline(1) =~# '^tree ' && getline(2) == "")
|
|
|
|
|
|
|
|
if getline('.') =~# '^ref: '
|
|
|
|
let ref = strpart(getline('.'),5)
|
|
|
|
|
2011-08-19 02:43:31 -04:00
|
|
|
elseif getline('.') =~# '^commit \x\{40\}\>'
|
|
|
|
let ref = matchstr(getline('.'),'\x\{40\}')
|
|
|
|
return s:Edit(a:mode,0,ref)
|
|
|
|
|
2009-10-10 19:47:14 -04:00
|
|
|
elseif getline('.') =~# '^parent \x\{40\}\>'
|
|
|
|
let ref = matchstr(getline('.'),'\x\{40\}')
|
|
|
|
let line = line('.')
|
|
|
|
let parent = 0
|
|
|
|
while getline(line) =~# '^parent '
|
|
|
|
let parent += 1
|
|
|
|
let line -= 1
|
|
|
|
endwhile
|
2011-08-19 02:43:31 -04:00
|
|
|
return s:Edit(a:mode,0,ref)
|
2009-10-10 19:47:14 -04:00
|
|
|
|
|
|
|
elseif getline('.') =~ '^tree \x\{40\}$'
|
|
|
|
let ref = matchstr(getline('.'),'\x\{40\}')
|
|
|
|
if s:repo().rev_parse(myhash.':') == ref
|
|
|
|
let ref = myhash.':'
|
|
|
|
endif
|
2011-08-19 02:43:31 -04:00
|
|
|
return s:Edit(a:mode,0,ref)
|
2009-10-10 19:47:14 -04:00
|
|
|
|
|
|
|
elseif getline('.') =~# '^object \x\{40\}$' && getline(line('.')+1) =~ '^type \%(commit\|tree\|blob\)$'
|
|
|
|
let ref = matchstr(getline('.'),'\x\{40\}')
|
|
|
|
let type = matchstr(getline(line('.')+1),'type \zs.*')
|
|
|
|
|
|
|
|
elseif getline('.') =~# '^\l\{3,8\} '.myhash.'$'
|
|
|
|
return ''
|
|
|
|
|
|
|
|
elseif getline('.') =~# '^\l\{3,8\} \x\{40\}\>'
|
|
|
|
let ref = matchstr(getline('.'),'\x\{40\}')
|
|
|
|
echoerr "warning: unknown context ".matchstr(getline('.'),'^\l*')
|
|
|
|
|
|
|
|
elseif getline('.') =~# '^[+-]\{3\} [ab/]'
|
|
|
|
let ref = getline('.')[4:]
|
|
|
|
|
2011-10-01 16:48:39 -04:00
|
|
|
elseif getline('.') =~# '^[+-]' && search('^@@ -\d\+,\d\+ +\d\+,','bnW')
|
|
|
|
let type = getline('.')[0]
|
|
|
|
let lnum = line('.') - 1
|
|
|
|
let offset = -1
|
|
|
|
while getline(lnum) !~# '^@@ -\d\+,\d\+ +\d\+,'
|
|
|
|
if getline(lnum) =~# '^[ '.type.']'
|
|
|
|
let offset += 1
|
|
|
|
endif
|
|
|
|
let lnum -= 1
|
|
|
|
endwhile
|
|
|
|
let offset += matchstr(getline(lnum), type.'\zs\d\+')
|
|
|
|
let ref = getline(search('^'.type.'\{3\} [ab]/','bnW'))[4:-1]
|
2014-06-10 18:46:04 -04:00
|
|
|
let dcmd = '+'.offset.'|normal! zv'
|
2011-10-01 16:48:39 -04:00
|
|
|
let dref = ''
|
|
|
|
|
2009-10-18 18:12:36 -04:00
|
|
|
elseif getline('.') =~# '^rename from '
|
|
|
|
let ref = 'a/'.getline('.')[12:]
|
|
|
|
elseif getline('.') =~# '^rename to '
|
|
|
|
let ref = 'b/'.getline('.')[10:]
|
|
|
|
|
|
|
|
elseif getline('.') =~# '^diff --git \%(a/.*\|/dev/null\) \%(b/.*\|/dev/null\)'
|
|
|
|
let dref = matchstr(getline('.'),'\Cdiff --git \zs\%(a/.*\|/dev/null\)\ze \%(b/.*\|/dev/null\)')
|
|
|
|
let ref = matchstr(getline('.'),'\Cdiff --git \%(a/.*\|/dev/null\) \zs\%(b/.*\|/dev/null\)')
|
2010-06-28 11:50:44 -04:00
|
|
|
let dcmd = 'Gdiff'
|
|
|
|
|
|
|
|
elseif getline('.') =~# '^index ' && getline(line('.')-1) =~# '^diff --git \%(a/.*\|/dev/null\) \%(b/.*\|/dev/null\)'
|
|
|
|
let line = getline(line('.')-1)
|
|
|
|
let dref = matchstr(line,'\Cdiff --git \zs\%(a/.*\|/dev/null\)\ze \%(b/.*\|/dev/null\)')
|
|
|
|
let ref = matchstr(line,'\Cdiff --git \%(a/.*\|/dev/null\) \zs\%(b/.*\|/dev/null\)')
|
|
|
|
let dcmd = 'Gdiff!'
|
2009-10-18 18:12:36 -04:00
|
|
|
|
2009-10-10 19:47:14 -04:00
|
|
|
elseif line('$') == 1 && getline('.') =~ '^\x\{40\}$'
|
|
|
|
let ref = getline('.')
|
2013-05-03 19:28:50 -04:00
|
|
|
|
|
|
|
elseif expand('<cword>') =~# '^\x\{7,40\}\>'
|
|
|
|
return s:Edit(a:mode,0,expand('<cword>'))
|
|
|
|
|
2009-10-10 19:47:14 -04:00
|
|
|
else
|
|
|
|
let ref = ''
|
|
|
|
endif
|
|
|
|
|
2009-10-18 18:12:36 -04:00
|
|
|
if myhash ==# ''
|
|
|
|
let ref = s:sub(ref,'^a/','HEAD:')
|
|
|
|
let ref = s:sub(ref,'^b/',':0:')
|
|
|
|
if exists('dref')
|
|
|
|
let dref = s:sub(dref,'^a/','HEAD:')
|
|
|
|
endif
|
|
|
|
else
|
2009-10-10 19:47:14 -04:00
|
|
|
let ref = s:sub(ref,'^a/',myhash.'^:')
|
|
|
|
let ref = s:sub(ref,'^b/',myhash.':')
|
2009-10-18 18:12:36 -04:00
|
|
|
if exists('dref')
|
|
|
|
let dref = s:sub(dref,'^a/',myhash.'^:')
|
|
|
|
endif
|
2009-10-10 19:47:14 -04:00
|
|
|
endif
|
|
|
|
|
2010-01-09 17:35:27 -05:00
|
|
|
if ref ==# '/dev/null'
|
2009-10-10 19:47:14 -04:00
|
|
|
" Empty blob
|
|
|
|
let ref = 'e69de29bb2d1d6434b8b29ae775ad8c2e48c5391'
|
|
|
|
endif
|
|
|
|
|
2009-10-18 18:12:36 -04:00
|
|
|
if exists('dref')
|
2011-08-19 02:43:31 -04:00
|
|
|
return s:Edit(a:mode,0,ref) . '|'.dcmd.' '.s:fnameescape(dref)
|
2009-10-18 18:12:36 -04:00
|
|
|
elseif ref != ""
|
2011-08-19 02:43:31 -04:00
|
|
|
return s:Edit(a:mode,0,ref)
|
2009-10-10 19:47:14 -04:00
|
|
|
endif
|
|
|
|
|
|
|
|
endif
|
|
|
|
return ''
|
|
|
|
catch /^fugitive:/
|
|
|
|
return 'echoerr v:errmsg'
|
|
|
|
endtry
|
|
|
|
endfunction
|
|
|
|
|
2014-06-21 08:48:11 -04:00
|
|
|
" Section: Statusline
|
2010-02-02 23:46:04 -05:00
|
|
|
|
|
|
|
function! s:repo_head_ref() dict abort
|
2014-03-30 13:13:46 -04:00
|
|
|
if !filereadable(self.dir('HEAD'))
|
|
|
|
return ''
|
|
|
|
endif
|
2012-03-18 21:55:53 -04:00
|
|
|
return readfile(self.dir('HEAD'))[0]
|
2010-02-02 23:46:04 -05:00
|
|
|
endfunction
|
|
|
|
|
|
|
|
call s:add_methods('repo',['head_ref'])
|
|
|
|
|
2014-03-27 17:22:35 -04:00
|
|
|
function! fugitive#statusline(...) abort
|
2010-02-02 23:46:04 -05:00
|
|
|
if !exists('b:git_dir')
|
|
|
|
return ''
|
|
|
|
endif
|
2010-02-10 10:07:56 -05:00
|
|
|
let status = ''
|
2010-02-02 23:46:04 -05:00
|
|
|
if s:buffer().commit() != ''
|
|
|
|
let status .= ':' . s:buffer().commit()[0:7]
|
|
|
|
endif
|
2012-05-07 11:41:25 -04:00
|
|
|
let status .= '('.fugitive#head(7).')'
|
2010-02-10 10:07:56 -05:00
|
|
|
if &statusline =~# '%[MRHWY]' && &statusline !~# '%[mrhwy]'
|
|
|
|
return ',GIT'.status
|
|
|
|
else
|
|
|
|
return '[Git'.status.']'
|
|
|
|
endif
|
2010-02-02 23:46:04 -05:00
|
|
|
endfunction
|
|
|
|
|
2014-03-27 17:22:35 -04:00
|
|
|
function! fugitive#head(...) abort
|
2012-04-17 15:28:11 -04:00
|
|
|
if !exists('b:git_dir')
|
|
|
|
return ''
|
|
|
|
endif
|
|
|
|
|
|
|
|
return s:repo().head(a:0 ? a:1 : 0)
|
|
|
|
endfunction
|
|
|
|
|
2015-06-14 20:06:38 -04:00
|
|
|
augroup fugitive_statusline
|
|
|
|
autocmd!
|
|
|
|
autocmd User Flags call Hoist('buffer', function('fugitive#statusline'))
|
|
|
|
augroup END
|
|
|
|
|
2014-06-21 08:48:11 -04:00
|
|
|
" Section: Folding
|
2011-11-20 15:32:32 -05:00
|
|
|
|
|
|
|
function! fugitive#foldtext() abort
|
|
|
|
if &foldmethod !=# 'syntax'
|
|
|
|
return foldtext()
|
|
|
|
elseif getline(v:foldstart) =~# '^diff '
|
|
|
|
let [add, remove] = [-1, -1]
|
|
|
|
let filename = ''
|
|
|
|
for lnum in range(v:foldstart, v:foldend)
|
2012-10-21 22:54:59 -04:00
|
|
|
if filename ==# '' && getline(lnum) =~# '^[+-]\{3\} [abciow12]/'
|
2011-11-20 15:32:32 -05:00
|
|
|
let filename = getline(lnum)[6:-1]
|
|
|
|
endif
|
|
|
|
if getline(lnum) =~# '^+'
|
|
|
|
let add += 1
|
|
|
|
elseif getline(lnum) =~# '^-'
|
|
|
|
let remove += 1
|
|
|
|
elseif getline(lnum) =~# '^Binary '
|
|
|
|
let binary = 1
|
|
|
|
endif
|
|
|
|
endfor
|
|
|
|
if filename ==# ''
|
|
|
|
let filename = matchstr(getline(v:foldstart), '^diff .\{-\} a/\zs.*\ze b/')
|
|
|
|
endif
|
2012-10-21 23:21:12 -04:00
|
|
|
if filename ==# ''
|
|
|
|
let filename = getline(v:foldstart)[5:-1]
|
|
|
|
endif
|
2011-11-20 15:32:32 -05:00
|
|
|
if exists('binary')
|
|
|
|
return 'Binary: '.filename
|
|
|
|
else
|
|
|
|
return (add<10&&remove<100?' ':'') . add . '+ ' . (remove<10&&add<100?' ':'') . remove . '- ' . filename
|
|
|
|
endif
|
|
|
|
elseif getline(v:foldstart) =~# '^# .*:$'
|
|
|
|
let lines = getline(v:foldstart, v:foldend)
|
|
|
|
call filter(lines, 'v:val =~# "^#\t"')
|
|
|
|
cal map(lines,'s:sub(v:val, "^#\t%(modified: +|renamed: +)=", "")')
|
|
|
|
cal map(lines,'s:sub(v:val, "^([[:alpha:] ]+): +(.*)", "\\2 (\\1)")')
|
|
|
|
return getline(v:foldstart).' '.join(lines, ', ')
|
|
|
|
endif
|
|
|
|
return foldtext()
|
|
|
|
endfunction
|
|
|
|
|
|
|
|
augroup fugitive_foldtext
|
|
|
|
autocmd!
|
|
|
|
autocmd User Fugitive
|
|
|
|
\ if &filetype =~# '^git\%(commit\)\=$' && &foldtext ==# 'foldtext()' |
|
|
|
|
\ set foldtext=fugitive#foldtext() |
|
|
|
|
\ endif
|
|
|
|
augroup END
|