diff -Nru vim-fugitive-2.1/debian/changelog vim-fugitive-2.2/debian/changelog --- vim-fugitive-2.1/debian/changelog 2014-07-17 10:40:18.000000000 +0000 +++ vim-fugitive-2.2/debian/changelog 2015-02-09 15:25:14.000000000 +0000 @@ -1,3 +1,18 @@ +vim-fugitive (2.2-2) unstable; urgency=medium + + * Fixed debian watch again + + -- Andrea Capriotti Mon, 09 Feb 2015 16:24:43 +0100 + +vim-fugitive (2.2-1) unstable; urgency=medium + + * New upstream release + * Fixed debian watch + * Set Standards-Version to 3.9.6; no changes + * Fixed debian copyright file + + -- Andrea Capriotti Mon, 09 Feb 2015 15:41:33 +0100 + vim-fugitive (2.1-2) unstable; urgency=low * Added Vcs field in debian/control diff -Nru vim-fugitive-2.1/debian/control vim-fugitive-2.2/debian/control --- vim-fugitive-2.1/debian/control 2014-07-17 10:37:49.000000000 +0000 +++ vim-fugitive-2.2/debian/control 2015-02-09 14:49:45.000000000 +0000 @@ -3,7 +3,7 @@ Priority: extra Maintainer: Andrea Capriotti Build-Depends: debhelper (>= 9.0.0) -Standards-Version: 3.9.5 +Standards-Version: 3.9.6 Homepage: https://github.com/tpope/vim-fugitive Vcs-Git: git://anonscm.debian.org/collab-maint/vim-fugitive.git Vcs-Browser: http://anonscm.debian.org/gitweb?p=collab-maint/vim-fugitive.git;a=summary diff -Nru vim-fugitive-2.1/debian/copyright vim-fugitive-2.2/debian/copyright --- vim-fugitive-2.1/debian/copyright 2014-01-28 16:23:01.000000000 +0000 +++ vim-fugitive-2.2/debian/copyright 2015-02-09 15:03:06.000000000 +0000 @@ -4,9 +4,7 @@ Files: * Copyright: Copyright (c) Tim Pope. -License: - Distributed under the same terms as Vim itself. -Comment: Vim license +License: Vim I) There are no restrictions on distributing unmodified copies of Vim except that they must include this license text. You can also distribute unmodified parts of Vim, likewise unrestricted except that they must diff -Nru vim-fugitive-2.1/debian/watch vim-fugitive-2.2/debian/watch --- vim-fugitive-2.1/debian/watch 2014-07-17 10:39:36.000000000 +0000 +++ vim-fugitive-2.2/debian/watch 2015-02-09 15:24:08.000000000 +0000 @@ -1,2 +1,6 @@ version=3 -http://githubredir.debian.net/github/tpope/vim-fugitive/ v(.*).tar.gz debian uupdate +opts=\ +filenamemangle=s/.+\/v?(\d\S*)\.tar\.gz/vim-fugitive-$1\.tar\.gz/,\ +uversionmangle=s/-/~/ \ + https://github.com/tpope/vim-fugitive/tags .*/v?(\d\S*)\.tar\.gz \ + debian uupdate diff -Nru vim-fugitive-2.1/doc/fugitive.txt vim-fugitive-2.2/doc/fugitive.txt --- vim-fugitive-2.1/doc/fugitive.txt 2014-06-24 20:38:01.000000000 +0000 +++ vim-fugitive-2.2/doc/fugitive.txt 2015-01-20 06:37:22.000000000 +0000 @@ -63,12 +63,32 @@ to commit, |:Gstatus| is called instead. Unless the arguments given would skip the invocation of an editor (e.g., -m), a split window will be used to obtain a - commit message. Write and close that window (:wq or - |:Gwrite|) to finish the commit. Unlike when running - the actual git-commit command, it is possible (but - unadvisable) to muck with the index with commands like - git-add and git-reset while a commit message is - pending. + commit message, or a new tab if -v is given. Write + and close that window (:wq or |:Gwrite|) to finish the + commit. Unlike when running the actual git-commit + command, it is possible (but unadvisable) to alter the + index with commands like git-add and git-reset while a + commit message is pending. + + *fugitive-:Gmerge* +:Gmerge [args] Calls git-merge and loads errors and conflicted files + into the quickfix list. Opens a |:Gcommit| style + split window for the commit message if the merge + succeeds. If called during a merge conflict, the + conflicted files from the current index are loaded + into the quickfix list. + + *fugitive-:Gpull* +:Gpull [args] Like |:Gmerge|, but for git-pull. + + *fugitive-:Gpush* +:Gpush [args] Invoke git-push, load the results into the quickfix + list, and invoke |:cwindow| to reveal any errors. + |:Dispatch| is used if available for asynchronous + invocation. + + *fugitive-:Gfetch* +:Gfetch [args] Like |:Gpush|, but for git-fetch. *fugitive-:Ggrep* :Ggrep [args] |:grep| with git-grep as 'grepprg'. @@ -84,6 +104,11 @@ previous commits rather than previous file revisions are loaded. +:{range}Glog [args] Use git-log -L to load previous revisions of the given + range of the current file into the quickfix list. The + cursor is positioned on the first line of the first + diff hunk for each commit. + *fugitive-:Gllog* :Gllog [args] Like |:Glog|, but use the location list instead of the quickfix list. diff -Nru vim-fugitive-2.1/plugin/fugitive.vim vim-fugitive-2.2/plugin/fugitive.vim --- vim-fugitive-2.1/plugin/fugitive.vim 2014-06-24 20:38:01.000000000 +0000 +++ vim-fugitive-2.2/plugin/fugitive.vim 2015-01-20 06:37:22.000000000 +0000 @@ -1,6 +1,6 @@ " fugitive.vim - A Git wrapper so awesome, it should be illegal " Maintainer: Tim Pope -" Version: 2.1 +" Version: 2.2 " GetLatestVimScripts: 2975 1 :AutoInstall: fugitive.vim if exists('g:loaded_fugitive') || &cp @@ -145,6 +145,13 @@ if root ==# $GIT_WORK_TREE && fugitive#is_git_dir($GIT_DIR) return $GIT_DIR endif + if fugitive#is_git_dir($GIT_DIR) + " Ensure that we've cached the worktree + call s:configured_tree($GIT_DIR) + if has_key(s:dir_for_worktree, root) + return s:dir_for_worktree[root] + endif + endif let dir = s:sub(root, '[\/]$', '') . '/.git' let type = getftype(dir) if type ==# 'dir' && fugitive#is_git_dir(dir) @@ -178,20 +185,34 @@ endif endif if exists('b:git_dir') - silent doautocmd User FugitiveBoot + if exists('#User#FugitiveBoot') + try + let [save_mls, &modelines] = [&mls, 0] + doautocmd User FugitiveBoot + finally + let &mls = save_mls + endtry + endif cnoremap fnameescape(recall()) nnoremap y :call setreg(v:register, recall()) let buffer = fugitive#buffer() if expand('%:p') =~# '//' call buffer.setvar('&path', s:sub(buffer.getvar('&path'), '^\.%(,|$)', '')) endif - if stridx(buffer.getvar('&tags'), escape(b:git_dir.'/tags', ', ')) == -1 - call buffer.setvar('&tags', escape(b:git_dir.'/tags', ', ').','.buffer.getvar('&tags')) - if &filetype !=# '' + 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') call buffer.setvar('&tags', escape(b:git_dir.'/'.&filetype.'.tags', ', ').','.buffer.getvar('&tags')) endif endif - silent doautocmd User Fugitive + try + let [save_mls, &modelines] = [&mls, 0] + doautocmd User Fugitive + finally + let &mls = save_mls + endtry endif endfunction @@ -209,6 +230,8 @@ let s:repo_prototype = {} let s:repos = {} +let s:worktree_for_dir = {} +let s:dir_for_worktree = {} function! s:repo(...) abort let dir = a:0 ? a:1 : (exists('b:git_dir') && b:git_dir !=# '' ? b:git_dir : fugitive#extract_git_dir(expand('%:p'))) @@ -232,21 +255,23 @@ return join([self.git_dir]+a:000,'/') endfunction -function! s:repo_configured_tree() dict abort - if !has_key(self,'_tree') - let self._tree = '' - if filereadable(self.dir('config')) - let config = readfile(self.dir('config'),'',10) +function! s:configured_tree(git_dir) abort + if !has_key(s:worktree_for_dir, a:git_dir) + let s:worktree_for_dir[a:git_dir] = '' + let config_file = a:git_dir . '/config' + if filereadable(config_file) + let config = readfile(config_file,'',10) call filter(config,'v:val =~# "^\\s*worktree *="') if len(config) == 1 - let self._tree = matchstr(config[0], '= *\zs.*') + let s:worktree_for_dir[a:git_dir] = matchstr(config[0], '= *\zs.*') + let s:dir_for_worktree[s:worktree_for_dir[a:git_dir]] = a:git_dir endif endif endif - if self._tree =~# '^\.' - return simplify(self.dir(self._tree)) + if s:worktree_for_dir[a:git_dir] =~# '^\.' + return simplify(a:git_dir . '/' . s:worktree_for_dir[a:git_dir]) else - return self._tree + return s:worktree_for_dir[a:git_dir] endif endfunction @@ -254,7 +279,7 @@ if self.dir() =~# '/\.git$' let dir = self.dir()[0:-6] else - let dir = self.configured_tree() + let dir = s:configured_tree(self.git_dir) endif if dir ==# '' call s:throw('no work tree') @@ -267,7 +292,7 @@ if self.dir() =~# '/\.git$' return 0 else - return self.configured_tree() ==# '' + return s:configured_tree(self.git_dir) ==# '' endif endfunction @@ -332,7 +357,7 @@ return branch endfunction -call s:add_methods('repo',['dir','configured_tree','tree','bare','translate','head']) +call s:add_methods('repo',['dir','tree','bare','translate','head']) function! s:repo_git_command(...) dict abort let git = g:fugitive_git_executable . ' --git-dir='.s:shellesc(self.git_dir) @@ -648,15 +673,19 @@ return matchstr(a:args, '\v\C\\@)") -function! s:Commit(args) abort +function! s:Commit(args, ...) abort + let repo = a:0 ? a:1 : s:repo() let cd = exists('*haslocaldir') && haslocaldir() ? 'lcd ' : 'cd ' let dir = getcwd() - let msgfile = s:repo().dir('COMMIT_EDITMSG') + let msgfile = repo.dir('COMMIT_EDITMSG') let outfile = tempname() let errorfile = tempname() try try - execute cd.s:fnameescape(s:repo().tree()) + execute cd.s:fnameescape(repo.tree()) if s:winshell() let command = '' let old_editor = $GIT_EDITOR @@ -976,7 +1006,7 @@ else let command = 'env GIT_EDITOR=false ' endif - let command .= s:repo().git_command('commit').' '.a:args + let command .= repo.git_command('commit').' '.a:args if &shell =~# 'csh' noautocmd silent execute '!('.command.' > '.outfile.') >& '.errorfile elseif a:args =~# '\%(^\| \)-\%(-interactive\|p\|-patch\)\>' @@ -1002,15 +1032,18 @@ let error = get(errors,-2,get(errors,-1,'!')) if error =~# 'false''\=\.$' let args = a:args - let args = s:gsub(args,'%(%(^| )-- )@' let args = '--cleanup=strip '.args endif if bufname('%') == '' && line('$') == 1 && getline(1) == '' && !&mod execute 'keepalt edit '.s:fnameescape(msgfile) + elseif a:args =~# '\%(^\| \)-\%(-verbose\|\w*v\)\>' + execute 'keepalt tabedit '.s:fnameescape(msgfile) elseif s:buffer().type() ==# 'index' execute 'keepalt edit '.s:fnameescape(msgfile) execute (search('^#','n')+1).'wincmd+' @@ -1052,11 +1085,130 @@ let args = getbufvar(+expand(''),'fugitive_commit_arguments') if !empty(args) call setbufvar(+expand(''),'fugitive_commit_arguments','') - return s:Commit(args) + return s:Commit(args, s:repo(getbufvar(+expand(''),'git_dir'))) endif return '' endfunction +" Section: Gmerge, Gpull + +call s:command("-nargs=? -bang -complete=custom,s:RevisionComplete Gmerge " . + \ "execute s:Merge('merge', 0, )") +call s:command("-nargs=? -bang -complete=custom,s:RemoteComplete Gpull " . + \ "execute s:Merge('pull --progress', 0, )") + +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:%.%#,' + \ . '%-G%.%#%\e[K%.%#,' + \ . '%-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 + let &l:makeprg = s:sub(g:fugitive_git_executable.' -c core.editor=false '. + \ a:cmd . (a:args =~# ' \%(--no-edit\|--abort\|-m\)\>' ? '' : ' --edit') . ' ' . a:args, + \ ' *$', '') + endif + if !empty($GIT_EDITOR) + let old_editor = $GIT_EDITOR + let $GIT_EDITOR = 'false' + 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 + return 'Gcommit --no-status -n -t '.s:shellesc(s:repo().dir('MERGE_MSG')) + 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 + " Section: Ggrep, Glog if !exists('g:fugitive_summary_format') @@ -1065,8 +1217,8 @@ call s:command("-bang -nargs=? -complete=customlist,s:EditComplete Ggrep :execute s:Grep('grep',0,)") call s:command("-bang -nargs=? -complete=customlist,s:EditComplete Glgrep :execute s:Grep('lgrep',0,)") -call s:command("-bar -bang -nargs=* -range=0 -complete=customlist,s:EditComplete Glog :call s:Log('grep',,)") -call s:command("-bar -bang -nargs=* -complete=customlist,s:EditComplete Gllog :call s:Log('lgrep',,)") +call s:command("-bar -bang -nargs=* -range=0 -complete=customlist,s:EditComplete Glog :call s:Log('grep',,,)") +call s:command("-bar -bang -nargs=* -range=0 -complete=customlist,s:EditComplete Gllog :call s:Log('lgrep',,,)") function! s:Grep(cmd,bang,arg) abort let grepprg = &grepprg @@ -1107,13 +1259,13 @@ endtry endfunction -function! s:Log(cmd, count, ...) abort +function! s:Log(cmd, line1, line2, ...) abort let path = s:buffer().path('/') if path =~# '^/\.git\%(/\|$\)' || index(a:000,'--') != -1 let path = '' endif let cmd = ['--no-pager', 'log', '--no-color'] - let cmd += ['--pretty=format:fugitive://'.s:repo().dir().'//%H'.path.':'.(a:count ? a:count : '').'::'.g:fugitive_summary_format] + let cmd += ['--pretty=format:fugitive://'.s:repo().dir().'//%H'.path.'::'.g:fugitive_summary_format] if empty(filter(a:000[0 : index(a:000,'--')],'v:val !~# "^-"')) if s:buffer().commit() =~# '\x\{40\}' let cmd += [s:buffer().commit()] @@ -1123,7 +1275,11 @@ end let cmd += map(copy(a:000),'s:sub(v:val,"^\\%(%(:\\w)*)","\\=fnamemodify(s:buffer().path(),submatch(1))")') if path =~# '/.' - let cmd += ['--',path[1:-1]] + if a:line2 + let cmd += ['-L', a:line1 . ',' . a:line2 . ':' . path[1:-1]] + else + let cmd += ['--', path[1:-1]] + endif endif let grepformat = &grepformat let grepprg = &grepprg @@ -1132,7 +1288,7 @@ try execute cd.'`=s:repo().tree()`' let &grepprg = escape(call(s:repo().git_command,cmd,s:repo()),'%#') - let &grepformat = '%f:%l::%m,%f:::%m' + let &grepformat = '%Cdiff %.%#,%C--- %.%#,%C+++ %.%#,%Z@@ -%\d%\+\,%\d%\+ +%l\,%\d%\+ @@,%-G-%.%#,%-G+%.%#,%-G %.%#,%A%f::%m,%-G%.%#' exe a:cmd finally let &grepformat = grepformat @@ -1401,6 +1557,35 @@ autocmd VimLeavePre,BufDelete COMMIT_EDITMSG execute s:sub(s:FinishCommit(), '^echoerr (.*)', 'echohl ErrorMsg|echo \1|echohl NONE') augroup END +" Section: Gpush, Gfetch + +call s:command("-nargs=? -bang -complete=custom,s:RemoteComplete Gpush execute s:Dispatch('', 'push '.)") +call s:command("-nargs=? -bang -complete=custom,s:RemoteComplete Gfetch execute s:Dispatch('', 'fetch '.)") + +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 + " Section: Gdiff call s:command("-bang -bar -nargs=* -complete=customlist,s:EditComplete Gdiff :execute s:Diff('',)") @@ -1666,6 +1851,7 @@ autocmd FileType fugitiveblame setlocal nomodeline | if exists('b:git_dir') | let &l:keywordprg = s:repo().keywordprg() | endif autocmd Syntax fugitiveblame call s:BlameSyntax() autocmd User Fugitive if s:buffer().type('file', 'blob') | exe "command! -buffer -bar -bang -range=0 -nargs=* Gblame :execute s:Blame(0,,,,[])" | endif + autocmd ColorScheme,GUIEnter * call s:RehighlightBlame() augroup END function! s:linechars(pattern) abort @@ -1679,6 +1865,9 @@ endfunction function! s:Blame(bang,line1,line2,count,args) abort + if exists('b:fugitive_blamed_bufnr') + return 'bdelete' + endif try if s:buffer().path() == '' call s:throw('file or blob required') @@ -1720,12 +1909,18 @@ endif for winnr in range(winnr('$'),1,-1) call setwinvar(winnr, '&scrollbind', 0) + if exists('+cursorbind') + call setwinvar(winnr, '&cursorbind', 0) + endif if getbufvar(winbufnr(winnr), 'fugitive_blamed_bufnr') execute winbufnr(winnr).'bdelete' endif endfor let bufnr = bufnr('') let restore = 'call setwinvar(bufwinnr('.bufnr.'),"&scrollbind",0)' + if exists('+cursorbind') + let restore .= '|call setwinvar(bufwinnr('.bufnr.'),"&cursorbind",0)' + endif if &l:wrap let restore .= '|call setwinvar(bufwinnr('.bufnr.'),"&wrap",1)' endif @@ -1733,6 +1928,9 @@ let restore .= '|call setwinvar(bufwinnr('.bufnr.'),"&foldenable",1)' endif setlocal scrollbind nowrap nofoldenable + if exists('+cursorbind') + setlocal cursorbind + endif let top = line('w0') + &scrolloff let current = line('.') let s:temp_files[tolower(temp)] = { 'dir': s:repo().dir(), 'args': cmd } @@ -1743,6 +1941,9 @@ execute top normal! zt execute current + if exists('+cursorbind') + setlocal cursorbind + endif setlocal nomodified nomodifiable nonumber scrollbind nowrap foldcolumn=0 nofoldenable winfixwidth filetype=fugitiveblame if exists('+concealcursor') setlocal concealcursor=nc conceallevel=2 @@ -1854,6 +2055,8 @@ return '' endfunction +let s:hash_colors = {} + function! s:BlameSyntax() abort let b:current_syntax = 'fugitiveblame' let conceal = has('conceal') ? ' conceal' : '' @@ -1872,7 +2075,7 @@ syn match FugitiveblameNotCommittedYet "(\@<=Not Committed Yet\>" contained containedin=FugitiveblameAnnotation hi def link FugitiveblameBoundary Keyword hi def link FugitiveblameHash Identifier - hi def link FugitiveblameUncommitted Function + hi def link FugitiveblameUncommitted Ignore hi def link FugitiveblameTime PreProc hi def link FugitiveblameLineNumber Number hi def link FugitiveblameOriginalFile String @@ -1880,6 +2083,37 @@ hi def link FugitiveblameShort FugitiveblameDelimiter hi def link FugitiveblameDelimiter Delimiter hi def link FugitiveblameNotCommittedYet Comment + 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 endfunction " Section: Gbrowse @@ -1964,18 +2198,32 @@ let raw = remote endif - let url = s:github_url(s:repo(),raw,rev,commit,path,type,a:line1,a:count) - if url == '' - let url = s:instaweb_url(s:repo(),rev,commit,path,type,a:count > 0 ? a:line1 : 0) - endif + for Handler in g:fugitive_browse_handlers + let url = call(Handler, [{ + \ 'repo': s:repo(), + \ 'remote': raw, + \ 'revision': rev, + \ 'commit': commit, + \ 'path': path, + \ 'type': type, + \ 'line1': a:count > 0 ? a:line1 : 0, + \ 'line2': a:count > 0 ? a:count : 0}]) + if !empty(url) + break + endif + endfor - if url == '' - call s:throw("Instaweb failed to start and '".remote."' is not a GitHub remote") + if empty(url) + call s:throw("Instaweb failed to start and '".remote."' is not a supported remote") endif if a:bang - let @* = url + if has('clipboard') + let @* = url + endif return 'echomsg '.string(url) + elseif exists(':Browse') == 2 + return 'echomsg '.string(url).'|Browse '.url else return 'echomsg '.string(url).'|call netrw#NetrwBrowseX('.string(url).', 0)' endif @@ -1984,24 +2232,27 @@ endtry endfunction -function! s:github_url(repo,url,rev,commit,path,type,line1,line2) abort - let path = a:path +function! s:github_url(opts, ...) abort + if a:0 || type(a:opts) != type({}) + return '' + endif let domain_pattern = 'github\.com' let domains = exists('g:fugitive_github_domains') ? g:fugitive_github_domains : [] for domain in domains let domain_pattern .= '\|' . escape(split(domain, '://')[-1], '.') endfor - let repo = matchstr(a:url,'^\%(https\=://\|git://\|git@\)\=\zs\('.domain_pattern.'\)[/:].\{-\}\ze\%(\.git\)\=$') + let repo = matchstr(get(a:opts, 'remote'), '^\%(https\=://\|git://\|git@\)\=\zs\('.domain_pattern.'\)[/:].\{-\}\ze\%(\.git\)\=$') if repo ==# '' return '' endif + let path = a:opts.path if index(domains, 'http://' . matchstr(repo, '^[^:/]*')) >= 0 let root = 'http://' . s:sub(repo,':','/') else let root = 'https://' . s:sub(repo,':','/') endif if path =~# '^\.git/refs/heads/' - let branch = a:repo.git_chomp('config','branch.'.path[16:-1].'.merge')[11:-1] + let branch = a:opts.repo.git_chomp('config','branch.'.path[16:-1].'.merge')[11:-1] if branch ==# '' return root . '/commits/' . path[16:-1] else @@ -2014,27 +2265,27 @@ elseif path =~# '^\.git\>' return root endif - if a:rev =~# '^[[:alnum:]._-]\+:' - let commit = matchstr(a:rev,'^[^:]*') - elseif a:commit =~# '^\d\=$' - let local = matchstr(a:repo.head_ref(),'\ 0 && a:line1 == a:line2 - let url .= '#L' . a:line1 - elseif a:line2 > 0 - let url .= '#L' . a:line1 . '-' . a:line2 + if get(a:opts, 'line2') && a:opts.line1 == a:opts.line2 + let url .= '#L' . a:opts.line1 + elseif get(a:opts, 'line2') + let url .= '#L' . a:opts.line1 . '-' . a:opts.line2 endif - elseif a:type == 'tag' + elseif a:opts.type == 'tag' let commit = matchstr(getline(3),'^tag \zs.*') let url = root . '/tree/' . commit else @@ -2043,47 +2294,54 @@ return url endfunction -function! s:instaweb_url(repo,rev,commit,path,type,...) abort - let output = a:repo.git_chomp('instaweb','-b','unknown') +function! s:instaweb_url(opts) abort + let output = a:opts.repo.git_chomp('instaweb','-b','unknown') if output =~# 'http://' - let root = matchstr(output,'http://.*').'/?p='.fnamemodify(a:repo.dir(),':t') + let root = matchstr(output,'http://.*').'/?p='.fnamemodify(a:opts.repo.dir(),':t') else return '' endif - if a:path =~# '^\.git/refs/.' - return root . ';a=shortlog;h=' . matchstr(a:path,'^\.git/\zs.*') - elseif a:path =~# '^\.git\>' + if a:opts.path =~# '^\.git/refs/.' + return root . ';a=shortlog;h=' . matchstr(a:opts.path,'^\.git/\zs.*') + elseif a:opts.path =~# '^\.git\>' return root endif let url = root - if a:commit =~# '^\x\{40\}$' - if a:type ==# 'commit' + if a:opts.commit =~# '^\x\{40\}$' + if a:opts.type ==# 'commit' let url .= ';a=commit' endif - let url .= ';h=' . a:repo.rev_parse(a:commit . (a:path == '' ? '' : ':' . a:path)) + let url .= ';h=' . a:opts.repo.rev_parse(a:opts.commit . (a:opts.path == '' ? '' : ':' . a:opts.path)) else - if a:type ==# 'blob' + if a:opts.type ==# 'blob' let tmp = tempname() - silent execute 'write !'.a:repo.git_command('hash-object','-w','--stdin').' > '.tmp + silent execute 'write !'.a:opts.repo.git_command('hash-object','-w','--stdin').' > '.tmp let url .= ';h=' . readfile(tmp)[0] else try - let url .= ';h=' . a:repo.rev_parse((a:commit == '' ? 'HEAD' : ':' . a:commit) . ':' . a:path) + let url .= ';h=' . a:opts.repo.rev_parse((a:opts.commit == '' ? 'HEAD' : ':' . a:opts.commit) . ':' . a:opts.path) catch /^fugitive:/ call s:throw('fugitive: cannot browse uncommitted file') endtry endif - let root .= ';hb=' . matchstr(a:repo.head_ref(),'[^ ]\+$') + let root .= ';hb=' . matchstr(a:opts.repo.head_ref(),'[^ ]\+$') endif - if a:path !=# '' - let url .= ';f=' . a:path + if a:opts.path !=# '' + let url .= ';f=' . a:opts.path endif - if a:0 && a:1 - let url .= '#l' . a:1 + if get(a:opts, 'line1') + let url .= '#l' . a:opts.line1 endif return url endfunction +if !exists('g:fugitive_browse_handlers') + let g:fugitive_browse_handlers = [] +endif + +call extend(g:fugitive_browse_handlers, + \ [s:function('s:github_url'), s:function('s:instaweb_url')]) + " Section: File access function! s:ReplaceCmd(cmd,...) abort @@ -2260,7 +2518,9 @@ endif if v:shell_error == 0 setlocal nomodified - silent execute 'doautocmd BufWritePost '.s:fnameescape(expand('%:p')) + if exists('#BufWritePost') + execute 'doautocmd BufWritePost '.s:fnameescape(expand('%:p')) + endif call fugitive#reload_status() return '' else @@ -2387,7 +2647,7 @@ \ let b:git_type = 'temp' | \ let b:git_args = s:temp_files[tolower(expand(':p'))].args | \ call fugitive#detect(expand(':p')) | - \ setlocal bufhidden=delete | + \ setlocal bufhidden=delete nobuflisted | \ nnoremap q :bdelete| \ endif augroup END diff -Nru vim-fugitive-2.1/README.markdown vim-fugitive-2.2/README.markdown --- vim-fugitive-2.1/README.markdown 2014-06-24 20:38:01.000000000 +0000 +++ vim-fugitive-2.2/README.markdown 2015-01-20 06:37:22.000000000 +0000 @@ -55,15 +55,13 @@ ## Installation -If you don't have a preferred installation method, I recommend -installing [pathogen.vim](https://github.com/tpope/vim-pathogen), and -then simply copy and paste: +If you don't have a preferred installation method, one option is to install +[pathogen.vim](https://github.com/tpope/vim-pathogen), and then copy +and paste: cd ~/.vim/bundle git clone git://github.com/tpope/vim-fugitive.git - -Once help tags have been generated, you can view the manual with -`:help fugitive`. + vim -u NONE -c "helptags vim-fugitive/doc" -c q If your Vim version is below 7.2, I recommend also installing [vim-git](https://github.com/tpope/vim-git) for syntax highlighting and