55 Commits

Author SHA1 Message Date
Tim Pope
16c2b7abb9 Support worktrees
Closes https://github.com/tpope/vim-fugitive/issues/655
2016-02-24 16:20:52 -05:00
Tim Pope
1e3f1103d9 DRY up refs/ paths 2016-02-24 15:53:51 -05:00
Tim Pope
9835920a3c Use includeexpr on default <cfile>
Closes https://github.com/tpope/vim-fugitive/issues/744
2016-01-22 20:03:58 -05:00
Tim Pope
fd36aa9c61 Fix issue extracting remote 2016-01-08 17:05:54 -05:00
Tim Pope
4dd41688cf Entertain P as a p alternative in :Gstatus
This could potentially free up `p` as "open in new tab", which would
correspond nicely with `vim -p`.
2016-01-01 16:55:17 -05:00
Tim Pope
18d6d1ab82 Overhaul :Gbrowse remote handling 2015-12-26 19:53:07 -05:00
Tim Pope
9ce67cdc93 Always pass commit SHA to :Gbrowse handlers 2015-12-26 15:09:08 -05:00
Tim Pope
bf04261080 Revert "Remove guard against index stage in :Gbrowse handler"
This reverts commit 14daf094d9.  My
assertion was wrong; commit will no longer be an index stage but it
still might be an empty string.
2015-12-26 14:54:35 -05:00
Tim Pope
52d180af0a Include trailing / in tree paths for :Gbrowse handlers 2015-12-26 14:37:45 -05:00
Tim Pope
14daf094d9 Remove guard against index stage in :Gbrowse handler
This parameter can now always be directly used within a URL, without any
sanity checking
2015-12-26 14:36:39 -05:00
Tim Pope
ac904e806d Don't pass stage number as commit to :Gbrowse handler 2015-12-26 14:18:00 -05:00
Tim Pope
9f768cd3bc Minimum viable URL escaping in :Gbrowse
Closes https://github.com/tpope/vim-fugitive/issues/703.
2015-12-26 14:11:54 -05:00
Tim Pope
09cdce7add Fix jump to file for tree at root of commit
Closes https://github.com/tpope/vim-fugitive/issues/735
2015-12-23 21:27:43 -05:00
Tim Pope
8851b8fe64 Fix jump from diff to file
This code hasn't been touched in 4 years; how did it break?!
2015-12-15 21:19:33 -05:00
Tim Pope
cfa485ede7 Better support for binary file grep results 2015-12-15 19:01:40 -05:00
Tim Pope
207c643ea4 Bring GitHub handler in line with rhubarb.vim
Closes https://github.com/tpope/vim-fugitive/issues/730
2015-12-11 16:38:05 -05:00
Tim Pope
cac2c8ef8e Fix instaweb current buffer assumption 2015-12-01 18:41:29 -05:00
Tim Pope
a9a22e0e4e Never :Gedit with a trailing slash 2015-12-01 18:35:25 -05:00
Tim Pope
c3e918072f Accommodate @ as alias for HEAD 2015-12-01 18:06:38 -05:00
Tim Pope
d854197c03 Open release page for tags on GitHub 2015-12-01 04:04:55 -05:00
Tim Pope
d8ce8d1d03 Document transition to rhubarb.vim 2015-11-30 22:25:50 -05:00
Tim Pope
23faeadc7c Revert "Show all untracked files in :Gstatus window"
This reverts commit 21b6dd7aee.

Closes https://github.com/tpope/vim-fugitive/issues/726
2015-11-30 19:38:48 -05:00
Andy Russell
1ecd12d523 Add support for fish shell syntax
Closes #626.
2015-11-06 15:54:34 -05:00
Jerome Reybert
f8aa87a4b5 Fix when $GIT_DIR is set and is not an absolute path 2015-11-03 09:52:22 -05:00
Jacob Niehus
dba8a0705d Fix diff sometimes opening in preview window
If the previous window no longer exists when Gedit is called, the
attempt to change windows with 'wincmd p' fails and 'wincmd w' should be
used instead.
2015-10-16 23:48:38 -04:00
Tim Pope
8cf3d94a3a Support gf in git filetypes
Closes https://github.com/tpope/vim-fugitive/issues/697
2015-10-07 00:21:49 -04:00
Tim Pope
28de2a1ddd Enable jumping on @@ hunk header 2015-10-07 00:21:49 -04:00
Tim Pope
01cda4d443 :Gdiff! keeps window focus 2015-10-07 00:21:35 -04:00
Tim Pope
b5188a1b4f Accept +cmd with :Gdiff 2015-10-07 00:05:07 -04:00
Tim Pope
8e63140181 Resplit when :Gstatus is final window 2015-10-07 00:05:07 -04:00
Tim Pope
cec56ef5ff Extract current file logic from s:GF 2015-10-06 21:45:40 -04:00
Tim Pope
1e755064e9 Better error on :Gwrite failure
References https://github.com/tpope/vim-fugitive/issues/696
2015-10-06 20:33:41 -04:00
Daniel Hahler
0b43b51d77 Expand % instead of <amatch> in the Buf* autocommands
This is relevant in case a previous BufReadPost autocmd changes the file
name using `:file` - fugitive should use the new/current name then.
2015-10-02 19:40:37 -04:00
Daniel Hahler
5dcf8a0175 ReplaceCmd: redirect stderr to tmp file / buffer
The option `status.showUntrackedFiles=all` used with `git status` for
`:Gstatus` might cause an error, which then causes fugitive to display an
empty status window / index file.

Redirecting the stderr output is useful in this case.

The generated command was:

    git --git-dir=/home/user/.dotfiles/.git -c 'status.displayCommentPrefix=true' -c 'color.status=false' -c 'status.short=false' -c 'status.showUntrackedFiles=all' status

The error from git is related to submodules being moved to another
subdirectory, where the relative "gitdir" now does not exist anymore:

    fatal: Not a git repository: vim/bundle.old.nobackup/CLEAN/colorscheme-base16/../../../.git/modules/vim/bundle/colorscheme-base16

While that's a Git / user error after all, fugitive should be more
helpful in that case by displaying the error.

It uses the 'shellpipe' setting to detect if '2>&1' is supported (Ref:
https://github.com/tpope/vim-fugitive/pull/661#issuecomment-120438667).

Closes #661.
2015-10-02 19:39:07 -04:00
Daniel Hahler
2509641eac Add "stash" and stash refs in repo.superglob
This looks for `refs/stash` and calls `git stash list` to get all of
them in case it exists.
2015-10-02 19:27:35 -04:00
Tim Pope
073f3a37b9 Short circuit when jumping too far in blame history
References https://github.com/tpope/vim-fugitive/issues/607
2015-09-30 18:49:56 -04:00
David Elentok
b7b23001de Allow using the "%" variable in git commands
Closes https://github.com/tpope/vim-fugitive/issues/686

For example, when running:

  :Git add %

neovim throws the following exception:

  E499: Empty file name for '%' or '#',
  only works with ":p:h": terminal git add %

It is a result of the tabnew command, it creates a new blank tab where
"%" is empty.

This commit changes "tabnew" to "tabedit %" so you're still working on
the same file.

Once the command is done running the tab closes.
2015-09-10 15:32:35 -04:00
Patrick Davey
b319b69453 Add the "L" prefix which github requires for highlighting ranges now
Fixes https://github.com/tpope/vim-fugitive/issues/669
2015-08-02 15:26:14 -04:00
Pieter-Jan Van de Maele
03cc95cc19 Support for Ggrep when only %f is available 2015-07-20 15:06:06 -04:00
Tim Pope
7c4a906147 Support Vim without 'wildignorecase'
Closes #659.
2015-07-01 10:55:35 -04:00
Tim Pope
b5b2548a87 Support older Vim without 'fileignorecase' 2015-06-30 20:39:54 -04:00
Tim Pope
ca727b07f1 Better support for case insensitive file systems
Closes #451.
2015-06-30 17:43:16 -04:00
Tim Pope
0fbbe0b3a4 Open :Gcommit tab before current
Pretty ridiculous, but this seems to be the only way to return to the
right tab after closing the commit message.
2015-06-29 17:52:39 -04:00
Tim Pope
1c844375fa Add support for flagship.vim 2015-06-14 20:06:38 -04:00
Daniel Hahler
e065e4f841 (Re)store the current window in s:diffoff_all
This is required to make Vim execute the "Enter" autocommands when
closing the fugitive window.

Fixes: https://github.com/tpope/vim-fugitive/issues/421
2015-05-31 12:14:23 -04:00
Eli Young
21b6dd7aee Show all untracked files in :Gstatus window
Previously, if there were untracked files inside an untracked folder,
:Gstatus would only show the new folder. Attempting to run a diff on the
folder would pass the directory name, which would result in Vim opening
a directory listing. This makes :Gstatus list all untracked files, even
if they're inside untracked folders. This requires Git >=1.4, and will
silently fall back to the old behavior on earlier versions.

Closes #605.
2015-05-22 17:50:42 -04:00
Tim Pope
935a2cccd3 Don't close window after :Gremove
This is nothing more than a change in personal preference on my part.
It's particularly annoying when :Gstatus or the quickfix window is the
only other window open.
2015-05-19 12:27:22 -04:00
Tim Pope
c2908b174d Support older Git in :Gpull
Closes #645.
2015-05-19 11:15:30 -04:00
Diego Vera
b0e38f08dc Make Ggrep to work properly on Mac
- Color were causing to appear strange characters in the result.
- These characters made impossible to navigate the results
- The solution was to disable colors while executing git grep
2015-05-16 10:12:41 -04:00
Ole Reifschneider
4cc201cbe3 Use the neovim terminal emulator for :Git 2015-03-31 13:40:01 -04:00
Tim Pope
baa05dcfda Pass correct files to git reset --patch 2015-03-29 16:29:18 -04:00
Fedor Gusev
0095769029 Provide g:fugitive_no_maps to disable key maps
Add variable g:fugitive_no_maps. If set y<C-G> and <C-R><C-G> are not
mapped.

Resolves tpope/vim-fugitive#394
2015-02-20 15:50:02 -05:00
Eli Young
e8b94098bb Support browsing with new netrw.vim
The previous fix for #594 didn't handle the case in which the net netrw
was installed on older versions of Vim.
2015-02-20 15:49:36 -05:00
Tim Pope
eb8eb1850a Support for browsing with recent Vim
Closes #594.
2015-02-08 22:31:37 -05:00
Daniel Hahler
933f6a1e1d s:Diff: use winnr with <C-W>w instead of <C-W>p
This is more reliable and fixes an issue where the syntastic location
list of the original file would be focused after `:Gdiff`.

Ref: c99f0ff06b (commitcomment-9434351)
2015-01-25 19:23:45 -05:00
2 changed files with 330 additions and 158 deletions

View File

@@ -220,32 +220,40 @@ that are part of Git repositories).
:[range]Gblame [flags] Run git-blame on the given range.
*fugitive-:Gbrowse*
:[range]Gbrowse If the remote for the current branch is on GitHub,
open the current file, blob, tree, commit, or tag
(with git-web--browse) on GitHub. Otherwise, open the
current file, blob, tree, commit, or tag in
git-instaweb (if you have issues, verify you can run
"git instaweb" from a terminal). If a range is given,
it is appropriately appended to the URL as an anchor.
:Gbrowse Open the current file, blob, tree, commit, or tag
in your browser at the upstream hosting provider.
If a range is given, it is appropriately appended to
the URL as an anchor.
To use with GitHub FI, point g:fugitive_github_domains
at a list of domains:
>
let g:fugitive_github_domains = ['https://example.com']
~
:[range]Gbrowse! Like :Gbrowse, but put the URL on the clipboard rather
than opening it.
Upstream providers can be added by installing an
appropriate Vim plugin. For example, GitHub can be
supported by installing rhubarb.vim, available at
<https://github.com/tpope/vim-rhubarb>. (Native
support for GitHub is currently included, but that is
slated to be removed.)
:[range]Gbrowse {revision}
Like :Gbrowse, but for a given |fugitive-revision|. A
The hosting provider is determined by looking at the
remote for the current or specified branch and falls
back to "origin". In the special case of a "."
remote, a local instance of git-instaweb will be
started and used.
:Gbrowse {revision} Like :Gbrowse, but for a given |fugitive-revision|. A
useful value here is -, which ties the URL to the
latest commit rather than a volatile branch.
:[range]Gbrowse [...]@{remote}
Force using the given remote rather than the remote
:Gbrowse [...]@{remote} Force using the given remote rather than the remote
for the current branch. The remote is used to
determine which GitHub repository to link to.
:{range}Gbrowse [args] Appends an anchor to the URL that emphasizes the
selected lines. You almost certainly want to give a
"-" argument in this case to force the URL to include
an exact revision.
:[range]Gbrowse! [args] Like :Gbrowse, but put the URL on the clipboard rather
than opening it.
MAPPINGS *fugitive-mappings*
These maps are available everywhere.

View File

@@ -123,7 +123,9 @@ let s:abstract_prototype = {}
function! fugitive#is_git_dir(path) abort
let path = s:sub(a:path, '[\/]$', '') . '/'
return isdirectory(path.'objects') && isdirectory(path.'refs') && getfsize(path.'HEAD') > 10
return getfsize(path.'HEAD') > 10 && (
\ isdirectory(path.'objects') && isdirectory(path.'refs') ||
\ getftype(path.'commondir') ==# 'file')
endfunction
function! fugitive#extract_git_dir(path) abort
@@ -143,11 +145,11 @@ function! fugitive#extract_git_dir(path) abort
break
endif
if root ==# $GIT_WORK_TREE && fugitive#is_git_dir($GIT_DIR)
return $GIT_DIR
return simplify(fnamemodify(expand($GIT_DIR), ':p:s?[\/]$??'))
endif
if fugitive#is_git_dir($GIT_DIR)
" Ensure that we've cached the worktree
call s:configured_tree($GIT_DIR)
call s:configured_tree(simplify(fnamemodify(expand($GIT_DIR), ':p:s?[\/]$??')))
if has_key(s:dir_for_worktree, root)
return s:dir_for_worktree[root]
endif
@@ -193,8 +195,10 @@ function! fugitive#detect(path) abort
let &mls = save_mls
endtry
endif
cnoremap <buffer> <expr> <C-R><C-G> fnameescape(<SID>recall())
nnoremap <buffer> <silent> y<C-G> :call setreg(v:register, <SID>recall())<CR>
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
let buffer = fugitive#buffer()
if expand('%:p') =~# '//'
call buffer.setvar('&path', s:sub(buffer.getvar('&path'), '^\.%(,|$)', ''))
@@ -218,7 +222,7 @@ endfunction
augroup fugitive
autocmd!
autocmd BufNewFile,BufReadPost * call fugitive#detect(expand('<amatch>:p'))
autocmd BufNewFile,BufReadPost * call fugitive#detect(expand('%: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
@@ -263,9 +267,14 @@ function! s:configured_tree(git_dir) abort
let config = readfile(config_file,'',10)
call filter(config,'v:val =~# "^\\s*worktree *="')
if len(config) == 1
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
let worktree = matchstr(config[0], '= *\zs.*')
endif
elseif filereadable(a:git_dir . '/gitdir')
let worktree = fnamemodify(readfile(a:git_dir . '/gitdir')[0], ':h')
endif
if exists('worktree')
let s:worktree_for_dir[a:git_dir] = worktree
let s:dir_for_worktree[s:worktree_for_dir[a:git_dir]] = a:git_dir
endif
endif
if s:worktree_for_dir[a:git_dir] =~# '^\.'
@@ -297,6 +306,10 @@ function! s:repo_bare() dict abort
endfunction
function! s:repo_translate(spec) dict abort
let refs = self.dir('refs/')
if filereadable(self.dir('commondir'))
let refs = simplify(self.dir(get(readfile(self.dir('commondir'), 1), 0, ''))) . '/refs/'
endif
if a:spec ==# '.' || a:spec ==# '/.'
return self.bare() ? self.dir() : self.tree()
elseif a:spec =~# '^/\=\.git$' && self.bare()
@@ -318,18 +331,20 @@ function! s:repo_translate(spec) dict abort
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)
elseif filereadable(self.dir('refs/'.a:spec))
return self.dir('refs/'.a:spec)
elseif filereadable(self.dir('refs/tags/'.a:spec))
return self.dir('refs/tags/'.a:spec)
elseif filereadable(self.dir('refs/heads/'.a:spec))
return self.dir('refs/heads/'.a:spec)
elseif filereadable(self.dir('refs/remotes/'.a:spec))
return self.dir('refs/remotes/'.a:spec)
elseif filereadable(self.dir('refs/remotes/'.a:spec.'/HEAD'))
return self.dir('refs/remotes/'.a:spec,'/HEAD')
elseif a:spec ==# '@'
return self.dir('HEAD')
elseif a:spec =~# 'HEAD\|^refs/' && a:spec !~ ':' && filereadable(refs . '../' . a:spec)
return simplify(refs . '../' . a:spec)
elseif filereadable(refs.a:spec)
return refs.a:spec
elseif filereadable(refs.'tags/'.a:spec)
return refs.'tags/'.a:spec
elseif filereadable(refs.'heads/'.a:spec)
return refs.'heads/'.a:spec
elseif filereadable(refs.'remotes/'.a:spec)
return refs.'remotes/'.a:spec
elseif filereadable(refs.'remotes/'.a:spec.'/HEAD')
return refs.'remotes/'.a:spec,'/HEAD'
else
try
let ref = self.rev_parse(matchstr(a:spec,'[^:]*'))
@@ -402,6 +417,11 @@ function! s:repo_superglob(base) dict abort
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"))
" Add any stashes.
if filereadable(s:repo().dir('refs/stash'))
let heads += ["stash"]
let heads += sort(split(s:repo().git_chomp("stash","list","--pretty=format:%gd"),"\n"))
endif
call filter(heads,'v:val[ 0 : strlen(a:base)-1 ] ==# a:base')
let results += heads
endif
@@ -555,13 +575,24 @@ function! s:buffer_commit() dict abort
return matchstr(self.spec(),'^fugitive://.\{-\}//\zs\w*')
endfunction
function! s:cpath(path) abort
if exists('+fileignorecase') && &fileignorecase
return tolower(a:path)
else
return a:path
endif
endfunction
function! s:buffer_path(...) dict abort
let rev = matchstr(self.spec(),'^fugitive://.\{-\}//\zs.*')
if rev != ''
let rev = s:sub(rev,'\w*','')
elseif self.spec()[0 : len(self.repo().dir())] ==# self.repo().dir() . '/'
elseif s:cpath(self.spec()[0 : len(self.repo().dir())]) ==#
\ s:cpath(self.repo().dir() . '/')
let rev = '/.git'.self.spec()[strlen(self.repo().dir()) : -1]
elseif !self.repo().bare() && self.spec()[0 : len(self.repo().tree())] ==# self.repo().tree() . '/'
elseif !self.repo().bare() &&
\ s:cpath(self.spec()[0 : len(self.repo().tree())]) ==#
\ s:cpath(self.repo().tree() . '/')
let rev = self.spec()[strlen(self.repo().tree()) : -1]
endif
return s:sub(s:sub(rev,'.\zs/$',''),'^/',a:0 ? a:1 : '')
@@ -668,8 +699,17 @@ function! s:Git(bang, args) abort
let git .= ' --no-pager'
endif
let args = matchstr(a:args,'\v\C.{-}%($|\\@<!%(\\\\)*\|)@=')
call s:ExecuteInTree('!'.git.' '.args)
call fugitive#reload_status()
if exists(':terminal')
let dir = s:repo().tree()
tabedit %
execute 'lcd' fnameescape(dir)
execute 'terminal' git args
else
call s:ExecuteInTree('!'.git.' '.args)
if has('win32')
call fugitive#reload_status()
endif
endif
return matchstr(a:args, '\v\C\\@<!%(\\\\)*\|\zs.*')
endfunction
@@ -706,6 +746,7 @@ augroup fugitive_status
autocmd!
if !has('win32')
autocmd FocusGained,ShellCmdPost * call fugitive#reload_status()
autocmd BufDelete term://* call fugitive#reload_status()
endif
augroup END
@@ -971,7 +1012,7 @@ function! s:StagePatch(lnum1,lnum2) abort
execute "Git add --patch -- ".join(map(add,'s:shellesc(v:val)'))
endif
if !empty(reset)
execute "Git reset --patch -- ".join(map(add,'s:shellesc(v:val)'))
execute "Git reset --patch -- ".join(map(reset,'s:shellesc(v:val)'))
endif
if exists('first_filename')
silent! edit!
@@ -1043,7 +1084,7 @@ function! s:Commit(args, ...) abort
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)
execute 'keepalt '.(tabpagenr()-1).'tabedit '.s:fnameescape(msgfile)
elseif s:buffer().type() ==# 'index'
execute 'keepalt edit '.s:fnameescape(msgfile)
execute (search('^#','n')+1).'wincmd+'
@@ -1164,13 +1205,15 @@ function! s:Merge(cmd, bang, args) abort
\ !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,
\ ' *$', '')
let &l:makeprg = s:sub(g:fugitive_git_executable . ' ' . a:cmd .
\ (a:args =~# ' \%(--no-edit\|--abort\|-m\)\>' ? '' : ' --edit') .
\ ' ' . a:args, ' *$', '')
endif
if !empty($GIT_EDITOR)
if !empty($GIT_EDITOR) || has('win32')
let old_editor = $GIT_EDITOR
let $GIT_EDITOR = 'false'
else
let &l:makeprg = 'env GIT_EDITOR=false ' . &l:makeprg
endif
execute cd fnameescape(s:repo().tree())
silent noautocmd make!
@@ -1227,8 +1270,8 @@ function! s:Grep(cmd,bang,arg) abort
let dir = getcwd()
try
execute cd.'`=s:repo().tree()`'
let &grepprg = s:repo().git_command('--no-pager', 'grep', '-n')
let &grepformat = '%f:%l:%m'
let &grepprg = s:repo().git_command('--no-pager', 'grep', '-n', '--no-color')
let &grepformat = '%f:%l:%m,%m %f match%ts,%f'
exe a:cmd.'! '.escape(matchstr(a:arg,'\v\C.{-}%($|[''" ]\@=\|)@='),'|')
let list = a:cmd =~# '^l' ? getloclist(0) : getqflist()
for entry in list
@@ -1303,7 +1346,14 @@ function! s:Edit(cmd,bang,...) abort
let buffer = s:buffer()
if a:cmd !~# 'read'
if &previewwindow && getbufvar('','fugitive_type') ==# 'index'
wincmd p
if winnr('$') == 1
let tabs = (&go =~# 'e' || !has('gui_running')) && &stal && (tabpagenr('$') >= &stal)
execute 'rightbelow' (&lines - &previewheight - &cmdheight - tabs - 1 - !!&laststatus).'new'
elseif winnr('#')
wincmd p
else
wincmd w
endif
if &diff
let mywinnr = winnr()
for winnr in range(winnr('$'),1,-1)
@@ -1334,7 +1384,7 @@ function! s:Edit(cmd,bang,...) abort
return 'redraw|echo '.string(':!'.git.' '.args)
else
let temp = resolve(tempname())
let s:temp_files[tolower(temp)] = { 'dir': buffer.repo().dir(), 'args': arglist }
let s:temp_files[s:cpath(temp)] = { 'dir': buffer.repo().dir(), 'args': arglist }
silent execute a:cmd.' '.temp
if a:cmd =~# 'pedit'
wincmd P
@@ -1369,6 +1419,9 @@ function! s:Edit(cmd,bang,...) abort
catch /^fugitive:/
return 'echoerr v:errmsg'
endtry
if file !~# '^fugitive:'
let file = s:sub(file, '/$', '')
endif
if a:cmd ==# 'read'
return 'silent %delete_|read '.s:fnameescape(file).'|silent 1delete_|diffupdate|'.line('.')
else
@@ -1431,6 +1484,9 @@ function! s:Write(force,...) abort
let mytab = tabpagenr()
let mybufnr = bufnr('')
let path = a:0 ? join(a:000, ' ') : s:buffer().path()
if empty(path)
return 'echoerr '.string('fugitive: cannot determine file path')
endif
if path =~# '^:\d\>'
return 'write'.(a:force ? '! ' : ' ').s:fnameescape(s:repo().translate(s:buffer().expand(path)))
endif
@@ -1588,9 +1644,9 @@ endfunction
" Section: Gdiff
call s:command("-bang -bar -nargs=* -complete=customlist,s:EditComplete Gdiff :execute s:Diff('',<f-args>)")
call s:command("-bar -nargs=* -complete=customlist,s:EditComplete Gvdiff :execute s:Diff('keepalt vert ',<f-args>)")
call s:command("-bar -nargs=* -complete=customlist,s:EditComplete Gsdiff :execute s:Diff('keepalt ',<f-args>)")
call s:command("-bang -bar -nargs=* -complete=customlist,s:EditComplete Gdiff :execute s:Diff('',<bang>0,<f-args>)")
call s:command("-bang -bar -nargs=* -complete=customlist,s:EditComplete Gvdiff :execute s:Diff('keepalt vert ',<bang>0,<f-args>)")
call s:command("-bang -bar -nargs=* -complete=customlist,s:EditComplete Gsdiff :execute s:Diff('keepalt ',<bang>0,<f-args>)")
augroup fugitive_diff
autocmd!
@@ -1667,6 +1723,7 @@ function! s:diffoff() abort
endfunction
function! s:diffoff_all(dir) abort
let curwin = winnr()
for nr in range(1,winnr('$'))
if getwinvar(nr,'&diff')
if nr != winnr()
@@ -1678,6 +1735,7 @@ function! s:diffoff_all(dir) abort
endif
endif
endfor
execute curwin.'wincmd w'
endfunction
function! s:buffer_compare_age(commit) dict abort
@@ -1702,11 +1760,16 @@ endfunction
call s:add_methods('buffer',['compare_age'])
function! s:Diff(vert,...) abort
function! s:Diff(vert,keepfocus,...) abort
let args = copy(a:000)
let post = ''
if get(args, 0) =~# '^+'
let post = remove(args, 0)[1:-1]
endif
let vert = empty(a:vert) ? s:diff_modifier(2) : a:vert
if exists(':DiffGitCached')
return 'DiffGitCached'
elseif (!a:0 || a:1 == ':') && s:buffer().commit() =~# '^[0-1]\=$' && s:repo().git_chomp_in_tree('ls-files', '--unmerged', '--', s:buffer().path()) !=# ''
elseif (empty(args) || args[0] == ':') && s:buffer().commit() =~# '^[0-1]\=$' && s:repo().git_chomp_in_tree('ls-files', '--unmerged', '--', s:buffer().path()) !=# ''
let vert = empty(a:vert) ? s:diff_modifier(3) : a:vert
let nr = bufnr('')
execute 'leftabove '.vert.'split `=fugitive#buffer().repo().translate(s:buffer().expand('':2''))`'
@@ -1718,11 +1781,11 @@ function! s:Diff(vert,...) abort
call s:diffthis()
wincmd p
call s:diffthis()
return ''
elseif a:0
let arg = join(a:000, ' ')
return post
elseif len(args)
let arg = join(args, ' ')
if arg ==# ''
return ''
return post
elseif arg ==# '/'
let file = s:buffer().path('/')
elseif arg ==# ':'
@@ -1755,13 +1818,17 @@ function! s:Diff(vert,...) abort
else
execute 'leftabove '.vert.'diffsplit '.s:fnameescape(spec)
endif
let &l:readonly = &l:readonly
redraw
let w:fugitive_diff_restore = restore
let winnr = winnr()
if getwinvar('#', '&diff')
wincmd p
call feedkeys("\<C-W>p", 'n')
if !a:keepfocus
call feedkeys(winnr."\<C-W>w", 'n')
endif
endif
return ''
return post
catch /^fugitive:/
return 'echoerr v:errmsg'
endtry
@@ -1831,7 +1898,7 @@ function! s:Remove(force) abort
return 'echoerr '.string(v:errmsg)
else
call fugitive#reload_status()
return 'bdelete'.(a:force ? '!' : '')
return 'edit'.(a:force ? '!' : '')
endif
endfunction
@@ -1933,7 +2000,7 @@ function! s:Blame(bang,line1,line2,count,args) abort
endif
let top = line('w0') + &scrolloff
let current = line('.')
let s:temp_files[tolower(temp)] = { 'dir': s:repo().dir(), 'args': cmd }
let s:temp_files[s:cpath(temp)] = { 'dir': s:repo().dir(), 'args': cmd }
exe 'keepalt leftabove vsplit '.temp
let b:fugitive_blamed_bufnr = bufnr
let w:fugitive_leave = restore
@@ -2043,15 +2110,17 @@ function! s:BlameJump(suffix) abort
if winnr > 0
exe bufnr.'bdelete'
endif
execute 'Gblame '.args
execute lnum
let delta = line('.') - line('w0') - offset
if delta > 0
execute 'normal! '.delta."\<C-E>"
elseif delta < 0
execute 'normal! '.(-delta)."\<C-Y>"
if exists(':Gblame')
execute 'Gblame '.args
execute lnum
let delta = line('.') - line('w0') - offset
if delta > 0
execute 'normal! '.delta."\<C-E>"
elseif delta < 0
execute 'normal! '.(-delta)."\<C-Y>"
endif
syncbind
endif
syncbind
return ''
endfunction
@@ -2118,11 +2187,18 @@ endfunction
" Section: Gbrowse
call s:command("-bar -bang -range -nargs=* -complete=customlist,s:EditComplete Gbrowse :execute s:Browse(<bang>0,<line1>,<count>,<f-args>)")
call s:command("-bar -bang -range=0 -nargs=* -complete=customlist,s:EditComplete Gbrowse :execute s:Browse(<bang>0,<line1>,<count>,<f-args>)")
function! s:Browse(bang,line1,count,...) abort
try
let rev = a:0 ? substitute(join(a:000, ' '),'@[[:alnum:]_-]*\%(://.\{-\}\)\=$','','') : ''
let validremote = '\.\|\.\=/.*\|[[:alnum:]_-]\+\%(://.\{-\}\)\='
if a:0
let remote = matchstr(join(a:000, ' '),'@\zs\%('.validremote.'\)$')
let rev = substitute(join(a:000, ' '),'@\%('.validremote.'\)$','','')
else
let remote = ''
let rev = ''
endif
if rev ==# ''
let expanded = s:buffer().rev()
elseif rev ==# ':'
@@ -2133,10 +2209,11 @@ function! s:Browse(bang,line1,count,...) abort
let full = s:repo().translate(expanded)
let commit = ''
if full =~# '^fugitive://'
let commit = matchstr(full,'://.*//\zs\w\+')
let commit = matchstr(full,'://.*//\zs\w\w\+')
let path = matchstr(full,'://.*//\w\+\zs/.*')
if commit =~ '..'
let type = s:repo().git_chomp('cat-file','-t',commit.s:sub(path,'^/',':'))
let branch = matchstr(expanded, '^[^:]*')
else
let type = 'blob'
endif
@@ -2154,6 +2231,9 @@ function! s:Browse(bang,line1,count,...) abort
let type = 'blob'
endif
endif
if type ==# 'tree' && !empty(path)
let path = s:sub(path, '/\=$', '/')
endif
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\}$'
@@ -2165,35 +2245,54 @@ function! s:Browse(bang,line1,count,...) abort
endif
endif
if a:0 && join(a:000, ' ') =~# '@[[:alnum:]_-]*\%(://.\{-\}\)\=$'
let remote = matchstr(join(a:000, ' '),'@\zs[[:alnum:]_-]\+\%(://.\{-\}\)\=$')
elseif path =~# '^\.git/refs/remotes/.'
let remote = matchstr(path,'^\.git/refs/remotes/\zs[^/]\+')
else
let remote = 'origin'
let branch = matchstr(rev,'^[[:alnum:]/._-]\+\ze[:^~@]')
if branch ==# '' && path =~# '^\.git/refs/\w\+/'
let branch = s:sub(path,'^\.git/refs/\w+/','')
let merge = ''
if path =~# '^\.git/refs/remotes/.'
if empty(remote)
let remote = matchstr(path, '^\.git/refs/remotes/\zs[^/]\+')
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.*')
let merge = matchstr(path, '^\.git/refs/remotes/[^/]\+/\zs.\+')
let branch = ''
let path = '.git/refs/heads/'.merge
elseif path =~# '^\.git/refs/heads/.'
let branch = path[16:-1]
elseif !exists('branch')
let branch = s:repo().head()
endif
if !empty(branch)
let r = s:repo().git_chomp('config','branch.'.branch.'.remote')
let m = s:repo().git_chomp('config','branch.'.branch.'.merge')[11:-1]
if r ==# '.' && !empty(m)
let r2 = s:repo().git_chomp('config','branch.'.m.'.remote')
if r2 !~# '^\.\=$'
let r = r2
let m = s:repo().git_chomp('config','branch.'.m.'.merge')[11:-1]
endif
if branch != ''
let remote = s:repo().git_chomp('config','branch.'.branch.'.remote')
if remote =~# '^\.\=$'
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
endif
if empty(remote)
let remote = r
endif
if r ==# '.' || r ==# remote
let merge = m
if path =~# '^\.git/refs/heads/.'
let path = '.git/refs/heads/'.merge
endif
endif
endif
let raw = s:repo().git_chomp('config','remote.'.remote.'.url')
if empty(commit) && path !~# '^\.git/'
if a:line1 && !a:count && !empty(merge)
let commit = merge
else
let commit = s:repo().rev_parse('HEAD')
endif
endif
if empty(remote)
let remote = '.'
let raw = s:repo().git_chomp('config','remote.origin.url')
else
let raw = s:repo().git_chomp('config','remote.'.remote.'.url')
endif
if raw ==# ''
let raw = remote
endif
@@ -2202,7 +2301,7 @@ function! s:Browse(bang,line1,count,...) abort
let url = call(Handler, [{
\ 'repo': s:repo(),
\ 'remote': raw,
\ 'revision': rev,
\ 'revision': 'No longer provided',
\ 'commit': commit,
\ 'path': path,
\ 'type': type,
@@ -2213,10 +2312,13 @@ function! s:Browse(bang,line1,count,...) abort
endif
endfor
if empty(url)
call s:throw("Instaweb failed to start and '".remote."' is not a supported remote")
if empty(url) && raw ==# '.'
call s:throw("Instaweb failed to start")
elseif empty(url)
call s:throw('"'.remote."' is not a supported remote")
endif
let url = s:gsub(url, '[ <>]', '\="%".printf("%02X",char2nr(submatch(0)))')
if a:bang
if has('clipboard')
let @* = url
@@ -2225,7 +2327,14 @@ function! s:Browse(bang,line1,count,...) abort
elseif exists(':Browse') == 2
return 'echomsg '.string(url).'|Browse '.url
else
return 'echomsg '.string(url).'|call netrw#NetrwBrowseX('.string(url).', 0)'
if !exists('g:loaded_netrw')
runtime! autoload/netrw.vim
endif
if exists('*netrw#BrowseX')
return 'echomsg '.string(url).'|call netrw#BrowseX('.string(url).', 0)'
else
return 'echomsg '.string(url).'|call netrw#NetrwBrowseX('.string(url).', 0)'
endif
endif
catch /^fugitive:/
return 'echoerr v:errmsg'
@@ -2245,7 +2354,7 @@ function! s:github_url(opts, ...) abort
if repo ==# ''
return ''
endif
let path = a:opts.path
let path = substitute(a:opts.path, '^/', '', '')
if index(domains, 'http://' . matchstr(repo, '^[^:/]*')) >= 0
let root = 'http://' . s:sub(repo,':','/')
else
@@ -2258,36 +2367,29 @@ function! s:github_url(opts, ...) abort
else
return root . '/commits/' . branch
endif
elseif path =~# '^\.git/refs/.'
return root . '/commits/' . matchstr(path,'[^/]\+$')
elseif path =~# '^\.git/refs/tags/'
return root . '/releases/tag/' . path[15:-1]
elseif path =~# '^\.git/refs/remotes/[^/]\+/.'
return root . '/commits/' . matchstr(path,'remotes/[^/]\+/\zs.*')
elseif path =~# '.git/\%(config$\|hooks\>\)'
return root . '/admin'
elseif path =~# '^\.git\>'
return root
endif
if a:opts.revision =~# '^[[:alnum:]._-]\+:'
let commit = matchstr(a:opts.revision,'^[^:]*')
elseif a:opts.commit =~# '^\d\=$'
let local = matchstr(a:opts.repo.head_ref(),'\<refs/heads/\zs.*')
let commit = a:opts.repo.git_chomp('config','branch.'.local.'.merge')[11:-1]
if commit ==# ''
let commit = local
endif
if a:opts.commit =~# '^\d\=$'
let commit = a:opts.repo.rev_parse('HEAD')
else
let commit = a:opts.commit
endif
if a:opts.type == 'tree'
let url = s:sub(root . '/tree/' . commit . '/' . path,'/$','')
elseif a:opts.type == 'blob'
if get(a:opts, 'type', '') ==# 'tree' || a:opts.path =~# '/$'
let url = substitute(root . '/tree/' . commit . '/' . path, '/$', '', 'g')
elseif get(a:opts, 'type', '') ==# 'blob' || a:opts.path =~# '[^/]$'
let url = root . '/blob/' . commit . '/' . path
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
let url .= '#L' . a:opts.line1 . '-L' . a:opts.line2
endif
elseif a:opts.type == 'tag'
let commit = matchstr(getline(3),'^tag \zs.*')
let url = root . '/tree/' . commit
else
let url = root . '/commit/' . commit
endif
@@ -2295,6 +2397,9 @@ function! s:github_url(opts, ...) abort
endfunction
function! s:instaweb_url(opts) abort
if a:opts.remote !=# '.'
return ''
endif
let output = a:opts.repo.git_chomp('instaweb','-b','unknown')
if output =~# 'http://'
let root = matchstr(output,'http://.*').'/?p='.fnamemodify(a:opts.repo.dir(),':t')
@@ -2313,10 +2418,8 @@ function! s:instaweb_url(opts) abort
endif
let url .= ';h=' . a:opts.repo.rev_parse(a:opts.commit . (a:opts.path == '' ? '' : ':' . a:opts.path))
else
if a:opts.type ==# 'blob'
let tmp = tempname()
silent execute 'write !'.a:opts.repo.git_command('hash-object','-w','--stdin').' > '.tmp
let url .= ';h=' . readfile(tmp)[0]
if a:opts.type ==# 'blob' && empty(a:opts.commit)
let url .= ';h='.a:opts.repo.git_chomp('hash-object', '-w', a:opts.path)
else
try
let url .= ';h=' . a:opts.repo.rev_parse((a:opts.commit == '' ? 'HEAD' : ':' . a:opts.commit) . ':' . a:opts.path)
@@ -2357,11 +2460,17 @@ function! s:ReplaceCmd(cmd,...) abort
let prefix = 'env GIT_INDEX_FILE='.s:shellesc(a:1).' '
endif
endif
let redir = ' > '.tmp
if &shellpipe =~ '2>&1'
let redir .= ' 2>&1'
endif
if s:winshell()
let cmd_escape_char = &shellxquote == '(' ? '^' : '^^^'
call system('cmd /c "'.prefix.s:gsub(a:cmd,'[<>]', cmd_escape_char.'&').' > '.tmp.'"')
call system('cmd /c "'.prefix.s:gsub(a:cmd,'[<>]', cmd_escape_char.'&').redir.'"')
elseif &shell =~# 'fish'
call system(' begin;'.prefix.a:cmd.redir.';end ')
else
call system(' ('.prefix.a:cmd.' > '.tmp.') ')
call system(' ('.prefix.a:cmd.redir.') ')
endif
finally
if exists('old_index')
@@ -2449,6 +2558,8 @@ function! s:BufReadIndex() abort
nnoremap <buffer> <silent> dv :<C-U>execute <SID>StageDiff('Gvdiff')<CR>
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>
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>
nnoremap <buffer> <silent> q :<C-U>if bufnr('$') == 1<Bar>quit<Bar>else<Bar>bdelete<Bar>endif<CR>
nnoremap <buffer> <silent> r :<C-U>edit<CR>
nnoremap <buffer> <silent> R :<C-U>edit<CR>
@@ -2631,6 +2742,10 @@ augroup fugitive_files
\ if exists('b:git_dir') |
\ call s:JumpInit() |
\ endif
autocmd FileType git,gitcommit,gitrebase
\ if exists('b:git_dir') |
\ call s:GFInit() |
\ endif
augroup END
" Section: Temp files
@@ -2642,10 +2757,10 @@ endif
augroup fugitive_temp
autocmd!
autocmd BufNewFile,BufReadPost *
\ if has_key(s:temp_files,tolower(expand('<afile>:p'))) |
\ let b:git_dir = s:temp_files[tolower(expand('<afile>:p'))].dir |
\ if has_key(s:temp_files,s:cpath(expand('<afile>:p'))) |
\ let b:git_dir = s:temp_files[s:cpath(expand('<afile>:p'))].dir |
\ let b:git_type = 'temp' |
\ let b:git_args = s:temp_files[tolower(expand('<afile>:p'))].args |
\ let b:git_args = s:temp_files[s:cpath(expand('<afile>:p'))].args |
\ call fugitive#detect(expand('<afile>:p')) |
\ setlocal bufhidden=delete nobuflisted |
\ nnoremap <buffer> <silent> q :<C-U>bdelete<CR>|
@@ -2654,7 +2769,18 @@ augroup END
" Section: Go to file
function! s:JumpInit() abort
nnoremap <SID>: :<C-U><C-R>=v:count ? v:count : ''<CR>
function! s:GFInit(...) abort
cnoremap <buffer> <expr> <Plug><cfile> fugitive#cfile()
if !exists('g:fugitive_no_maps') && empty(mapcheck('gf', 'n'))
nmap <buffer> <silent> gf <SID>:find <Plug><cfile><CR>
nmap <buffer> <silent> <C-W>f <SID>:sfind <Plug><cfile><CR>
nmap <buffer> <silent> <C-W><C-F> <SID>:sfind <Plug><cfile><CR>
nmap <buffer> <silent> <C-W>gf <SID>:tabfind <Plug><cfile><CR>
endif
endfunction
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>
@@ -2673,7 +2799,7 @@ function! s:JumpInit() abort
endif
endfunction
function! s:GF(mode) abort
function! s:cfile() abort
try
let buffer = s:buffer()
let myhash = buffer.sha1()
@@ -2683,12 +2809,10 @@ function! s:GF(mode) abort
if buffer.type('tree')
let showtree = (getline(1) =~# '^tree ' && getline(2) == "")
if showtree && line('.') == 1
return ""
elseif showtree && line('.') > 2
return s:Edit(a:mode,0,buffer.commit().':'.s:buffer().path().(buffer.path() =~# '^$\|/$' ? '' : '/').s:sub(getline('.'),'/$',''))
if showtree && line('.') > 2
return [buffer.commit().':'.s:buffer().path().(buffer.path() =~# '^$\|/$' ? '' : '/').s:sub(getline('.'),'/$','')]
elseif getline('.') =~# '^\d\{6\} \l\{3,8\} \x\{40\}\t'
return s:Edit(a:mode,0,buffer.commit().':'.s:buffer().path().(buffer.path() =~# '^$\|/$' ? '' : '/').s:sub(matchstr(getline('.'),'\t\zs.*'),'/$',''))
return [buffer.commit().':'.s:buffer().path().(buffer.path() =~# '^$\|/$' ? '' : '/').s:sub(matchstr(getline('.'),'\t\zs.*'),'/$','')]
endif
elseif buffer.type('blob')
@@ -2698,38 +2822,40 @@ function! s:GF(mode) abort
catch /^fugitive:/
endtry
if exists('sha1')
return s:Edit(a:mode,0,ref)
return [ref]
endif
else
let dcmds = []
" Index
if getline('.') =~# '^\d\{6\} \x\{40\} \d\t'
let ref = matchstr(getline('.'),'\x\{40\}')
let file = ':'.s:sub(matchstr(getline('.'),'\d\t.*'),'\t',':')
return s:Edit(a:mode,0,file)
return [file]
elseif getline('.') =~# '^#\trenamed:.* -> '
let file = '/'.matchstr(getline('.'),' -> \zs.*')
return s:Edit(a:mode,0,file)
return [file]
elseif getline('.') =~# '^#\t[[:alpha:] ]\+: *.'
let file = '/'.matchstr(getline('.'),': *\zs.\{-\}\ze\%( ([^()[:digit:]]\+)\)\=$')
return s:Edit(a:mode,0,file)
return [file]
elseif getline('.') =~# '^#\t.'
let file = '/'.matchstr(getline('.'),'#\t\zs.*')
return s:Edit(a:mode,0,file)
return [file]
elseif getline('.') =~# ': needs merge$'
let file = '/'.matchstr(getline('.'),'.*\ze: needs merge$')
return s:Edit(a:mode,0,file).'|Gdiff'
return [file, 'Gdiff!']
elseif getline('.') ==# '# Not currently on any branch.'
return s:Edit(a:mode,0,'HEAD')
return ['HEAD']
elseif getline('.') =~# '^# On branch '
let file = 'refs/heads/'.getline('.')[12:]
return s:Edit(a:mode,0,file)
return [file]
elseif getline('.') =~# "^# Your branch .*'"
let file = matchstr(getline('.'),"'\\zs\\S\\+\\ze'")
return s:Edit(a:mode,0,file)
return [file]
endif
let showtree = (getline(1) =~# '^tree ' && getline(2) == "")
@@ -2739,7 +2865,7 @@ function! s:GF(mode) abort
elseif getline('.') =~# '^commit \x\{40\}\>'
let ref = matchstr(getline('.'),'\x\{40\}')
return s:Edit(a:mode,0,ref)
return [ref]
elseif getline('.') =~# '^parent \x\{40\}\>'
let ref = matchstr(getline('.'),'\x\{40\}')
@@ -2749,21 +2875,21 @@ function! s:GF(mode) abort
let parent += 1
let line -= 1
endwhile
return s:Edit(a:mode,0,ref)
return [ref]
elseif getline('.') =~ '^tree \x\{40\}$'
let ref = matchstr(getline('.'),'\x\{40\}')
if s:repo().rev_parse(myhash.':') == ref
let ref = myhash.':'
endif
return s:Edit(a:mode,0,ref)
return [ref]
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 ''
let ref = buffer.rev()
elseif getline('.') =~# '^\l\{3,8\} \x\{40\}\>'
let ref = matchstr(getline('.'),'\x\{40\}')
@@ -2775,7 +2901,7 @@ function! s:GF(mode) abort
elseif getline('.') =~# '^[+-]' && search('^@@ -\d\+,\d\+ +\d\+,','bnW')
let type = getline('.')[0]
let lnum = line('.') - 1
let offset = -1
let offset = 0
while getline(lnum) !~# '^@@ -\d\+,\d\+ +\d\+,'
if getline(lnum) =~# '^[ '.type.']'
let offset += 1
@@ -2784,18 +2910,25 @@ function! s:GF(mode) abort
endwhile
let offset += matchstr(getline(lnum), type.'\zs\d\+')
let ref = getline(search('^'.type.'\{3\} [ab]/','bnW'))[4:-1]
let dcmd = '+'.offset.'|normal! zv'
let dref = ''
let dcmds = [offset, 'normal!zv']
elseif getline('.') =~# '^rename from '
let ref = 'a/'.getline('.')[12:]
elseif getline('.') =~# '^rename to '
let ref = 'b/'.getline('.')[10:]
elseif getline('.') =~# '^@@ -\d\+,\d\+ +\d\+,'
let diff = getline(search('^diff --git \%(a/.*\|/dev/null\) \%(b/.*\|/dev/null\)', 'bcnW'))
let offset = matchstr(getline('.'), '+\zs\d\+')
let dref = matchstr(diff, '\Cdiff --git \zs\%(a/.*\|/dev/null\)\ze \%(b/.*\|/dev/null\)')
let ref = matchstr(diff, '\Cdiff --git \%(a/.*\|/dev/null\) \zs\%(b/.*\|/dev/null\)')
let dcmd = 'Gdiff! +'.offset
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\)')
let dcmd = 'Gdiff'
let dcmd = 'Gdiff!'
elseif getline('.') =~# '^index ' && getline(line('.')-1) =~# '^diff --git \%(a/.*\|/dev/null\) \%(b/.*\|/dev/null\)'
let line = getline(line('.')-1)
@@ -2807,7 +2940,7 @@ function! s:GF(mode) abort
let ref = getline('.')
elseif expand('<cword>') =~# '^\x\{7,40\}\>'
return s:Edit(a:mode,0,expand('<cword>'))
return [expand('<cword>')]
else
let ref = ''
@@ -2833,16 +2966,42 @@ function! s:GF(mode) abort
endif
if exists('dref')
return s:Edit(a:mode,0,ref) . '|'.dcmd.' '.s:fnameescape(dref)
return [ref, dcmd . ' ' . s:fnameescape(dref)] + dcmds
elseif ref != ""
return s:Edit(a:mode,0,ref)
return [ref] + dcmds
endif
endif
return ''
return []
endtry
endfunction
function! s:GF(mode) abort
try
let results = s:cfile()
catch /^fugitive:/
return 'echoerr v:errmsg'
endtry
if len(results)
return s:Edit(a:mode, 0, results[0]).join(map(results[1:-1], '"|".v:val'), '')
else
return ''
endif
endfunction
function! fugitive#cfile() abort
let pre = ''
let results = s:cfile()
if empty(results)
let cfile = expand('<cfile>')
if &includeexpr =~# '\<v:fname\>'
sandbox let cfile = eval(substitute(&includeexpr, '\C\<v:fname\>', '\=string(cfile)', 'g'))
endif
return cfile
elseif len(results) > 1
let pre = '+' . join(map(results[1:-1], 'escape(v:val, " ")'), '\|') . ' '
endif
return pre . s:fnameescape(fugitive#repo().translate(results[0]))
endfunction
" Section: Statusline
@@ -2880,6 +3039,11 @@ function! fugitive#head(...) abort
return s:repo().head(a:0 ? a:1 : 0)
endfunction
augroup fugitive_statusline
autocmd!
autocmd User Flags call Hoist('buffer', function('fugitive#statusline'))
augroup END
" Section: Folding
function! fugitive#foldtext() abort