commit 1a7b07cf220eba986418bb2d29fc0fee3ee9cbf1 (tree)
parent 4a3c6b4a56dce19f3c1ac3f2f07988433cfcde87
Author: Tim Pope <code@tpope.net>
Date: Sat, 11 Aug 2018 00:52:48 -0400
Support commit:./relative style revisions
Diffstat:
| M | autoload/fugitive.vim | | | 92 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----------------- |
1 file changed, 72 insertions(+), 20 deletions(-)
diff --git a/autoload/fugitive.vim b/autoload/fugitive.vim
@@ -106,6 +106,15 @@ function! s:cpath(path, ...) abort
return a:0 ? path ==# s:cpath(a:1) : path
endfunction
+function! s:SubDir(cwd, ...) abort
+ let lead = (a:0 ? a:1 : s:Tree()) . '/'
+ if len(lead) && s:cpath(lead, strpart(a:cwd, 0, len(lead)))
+ return strpart(a:cwd, len(lead)) . '/'
+ else
+ return ''
+ endif
+endfunction
+
let s:executables = {}
function! s:executable(binary) abort
@@ -492,11 +501,20 @@ function! fugitive#Route(object, ...) abort
let prefix = matchstr(a:object, '^[~$]\i*')
let owner = expand(prefix)
return s:PlatformSlash((len(owner) ? owner : prefix) . strpart(a:object, len(prefix)))
- elseif s:Slash(a:object) =~# '^\%(\a\a\+:\)\=\%(a:\)\=/'
+ elseif s:Slash(a:object) =~# '^/\|^\%(\a\a\+:\).*\%(//\|::\)' || (has('win32') ? '^\a:/' : '')
return s:PlatformSlash(a:object)
endif
- let rev = substitute(a:object, '[:/]\zs\.\%(/\+\|$\)', '', 'g')
let dir = a:0 ? a:1 : get(b:, 'git_dir', '')
+ if empty(dir) && a:object =~# '^\.\.\=\%(/\|$\)'
+ return s:PlatformSlash(simplify(getcwd() . '/' . a:object[1:-1]))
+ elseif empty(dir)
+ let file = matchstr(a:object, '^\%(:\d:\|[^:]*:\)\zs.*', '', '')
+ let dir = FugitiveExtractGitDir(file)
+ if empty(dir)
+ return fnamemodify(len(file) ? file : a:object, ':p')
+ endif
+ endif
+ let rev = a:object
let tree = s:Tree(dir)
let base = len(tree) ? tree : 'fugitive://' . dir . '//0'
if rev =~# '^\%(\./\)\=\.git$' && empty(tree)
@@ -513,7 +531,23 @@ function! fugitive#Route(object, ...) abort
let f = base
elseif rev =~# '^\.\%(/\|$\)'
let f = base . rev[1:-1]
- elseif rev =~# '^:[0-3]:/\@!'
+ elseif rev =~# '^::\%(/\|\a\+\:\)'
+ let f = rev[2:-1]
+ elseif rev =~# '^::\.\.\=\%(/\|$\)'
+ let f = simplify(getcwd() . '/' . rev[2:-1])
+ elseif rev =~# '^::'
+ let f = base . '/' . rev[2:-1]
+ elseif rev =~# '^:\%([0-3]:\)\=\.\.\=\%(/\|$\)\|^:[0-3]:\%(/\|\a\+:\)'
+ let f = rev =~# '^:\%([0-3]:\)\=\.' ? simplify(getcwd() . '/' . matchstr(rev, '\..*')) : rev[3:-1]
+ if s:cpath(base . '/', (f . '/')[0 : len(base)])
+ let f = 'fugitive://' . dir . '//' . +matchstr(rev, '^:\zs\d\ze:') . '/' . strpart(f, len(base) + 1)
+ else
+ let altdir = FugitiveExtractGitDir(f)
+ if len(altdir) && !s:cpath(dir, altdir)
+ return fugitive#Route(a:object, altdir)
+ endif
+ endif
+ elseif rev =~# '^:[0-3]:'
let f = 'fugitive://' . dir . '//' . rev[1] . '/' . rev[3:-1]
elseif rev ==# ':'
if $GIT_INDEX_FILE =~# '/[^/]*index[^/]*\.lock$' && s:cpath(fnamemodify($GIT_INDEX_FILE,':p')[0:strlen(dir)]) ==# s:cpath(dir . '/') && filereadable($GIT_INDEX_FILE)
@@ -533,8 +567,20 @@ function! fugitive#Route(object, ...) abort
endif
endif
if !exists('f')
- let commit = substitute(matchstr(rev,'^[^:]\+\|^:.*'), '^@\%($|[^~]\)\@=', 'HEAD', '')
+ let commit = substitute(matchstr(rev, '^[^:]\+\|^:.*'), '^@\%($|[^~]\)\@=', 'HEAD', '')
let file = substitute(matchstr(rev, '^[^:]\+\zs:.*'), '^:', '/', '')
+ if file =~# '^/\.\.\=\%(/\|$\)\|^//\|^/\a\+:'
+ let file = file =~# '^/\.' ? simplify(getcwd() . file) : file[1:-1]
+ if s:cpath(base . '/', (file . '/')[0 : len(base)])
+ let file = '/' . strpart(file, len(base) + 1)
+ else
+ let altdir = FugitiveExtractGitDir(file)
+ if len(altdir) && !s:cpath(dir, altdir)
+ return fugitive#Route(a:object, altdir)
+ endif
+ return file
+ endif
+ endif
if commit !~# '^[0-9a-f]\{40\}$'
let commit = system(s:Prepare(dir, 'rev-parse', '--verify', commit))[0:-2]
let commit = v:shell_error ? '' : commit
@@ -542,7 +588,7 @@ function! fugitive#Route(object, ...) abort
if len(commit)
let f = 'fugitive://' . dir . '//' . commit . file
else
- let f = base . '/' . rev
+ let f = base . '/' . substitute(rev, '^:/:\=\|^[^:]\+:', '', '')
endif
endif
endif
@@ -553,8 +599,10 @@ function! s:Generate(rev, ...) abort
let dir = a:0 ? a:1 : get(b:, 'git_dir', '')
let tree = s:Tree(dir)
let object = a:rev
- if a:rev =~# '^/' && len(tree) && getftime(tree . a:rev) >= 0 && getftime(a:rev) < 0 || a:rev =~# '^/\.git\%(/\|$\)'
- let object = '.' . object
+ if a:rev =~# '^/\.git\%(/\|$\)'
+ let object = a:rev[1:-1]
+ elseif a:rev =~# '^/' && len(tree) && getftime(tree . a:rev) >= 0 && getftime(a:rev) < 0
+ let object = ':(top)' . a:rev[1:-1]
endif
return fugitive#Route(object, dir)
endfunction
@@ -613,7 +661,7 @@ function! s:Expand(rev) abort
let file = a:rev
endif
return s:sub(substitute(file,
- \ '\([%#]\)$\|\\\([[:punct:]]\)','\=len(submatch(2)) ? submatch(2) : fugitive#Path(expand(submatch(1)), "./", dir)','g'),
+ \ '\([%#]\)$\|\\\([[:punct:]]\)','\=len(submatch(2)) ? submatch(2) : fugitive#Path(expand(submatch(1)))','g'),
\ '\.\@<=/$','')
endfunction
@@ -1052,6 +1100,7 @@ endfunction
function! fugitive#Complete(base, ...) abort
let dir = a:0 == 1 ? a:1 : get(b:, 'git_dir', '')
+ let cwd = a:0 == 1 ? s:Tree(dir) : getcwd()
let tree = s:Tree(dir) . '/'
if a:base =~# '^\.\=/\|^:(' || a:base !~# ':'
let results = []
@@ -1069,28 +1118,31 @@ function! fugitive#Complete(base, ...) abort
endif
call map(results, 's:fnameescape(v:val)')
if !empty(tree)
- let results += fugitive#PathComplete(a:base, dir)
+ let results += a:0 == 1 ? fugitive#PathComplete(a:base, dir) : fugitive#PathComplete(a:base)
endif
return results
elseif a:base =~# '^:'
let entries = split(s:TreeChomp(['ls-files','--stage'], dir),"\n")
+ if a:base =~# ':\./'
+ let subdir = s:SubDir(cwd)
+ call map(entries, 'substitute(v:val, "\\M\t\\zs" . subdir, "./", "")')
+ endif
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 map(entries, 's:fnameescape(v:val)')
else
- let tree = matchstr(a:base,'.*[:/]')
- let entries = split(s:TreeChomp(['ls-tree',tree], dir),"\n")
+ let tree = matchstr(a:base, '.*[:/]')
+ let entries = split(s:TreeChomp(['ls-tree', substitute(tree, ':\zs\./', '\=s:SubDir(cwd)', '')], dir),"\n")
call map(entries,'s:sub(v:val,"^04.*\\zs$","/")')
call map(entries,'tree.s:sub(v:val,".*\t","")')
- call filter(entries,'v:val[ 0 : strlen(a:base)-1 ] ==# a:base')
- return map(entries, 's:fnameescape(v:val)')
+
endif
+ call filter(entries, 'v:val[ 0 : strlen(a:base)-1 ] ==# a:base')
+ return map(entries, 's:fnameescape(v:val)')
endfunction
" Section: Buffer auto-commands
@@ -1496,9 +1548,9 @@ function! s:GitComplete(A, L, P) abort
let cmds = s:Subcommands()
return filter(sort(cmds+keys(s:Aliases())), 'strpart(v:val, 0, strlen(a:A)) ==# a:A')
elseif pre =~# ' -- '
- return fugitive#PathComplete(a:A)
+ return fugitive#PathComplete(a:A, b:git_dir)
else
- return fugitive#Complete(a:A, a:L, a:P)
+ return fugitive#Complete(a:A, b:git_dir)
endif
endfunction
@@ -1920,7 +1972,7 @@ function! s:CommitComplete(A,L,P) abort
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=', '--fixup=', '--include', '--interactive', '--message=', '--no-verify', '--only', '--quiet', '--reedit-message=', '--reuse-message=', '--signoff', '--squash=', '--template=', '--untracked-files', '--verbose']
return filter(args,'v:val[0 : strlen(a:A)-1] ==# a:A')
else
- return fugitive#PathComplete(a:A)
+ return fugitive#PathComplete(a:A, b:git_dir)
endif
return []
endfunction
@@ -2068,9 +2120,9 @@ endif
function! s:GrepComplete(A, L, P) abort
if strpart(a:L, 0, a:P) =~# ' -- '
- return fugitive#PathComplete(a:A)
+ return fugitive#PathComplete(a:A, b:git_dir)
else
- return fugitive#Complete(a:A)
+ return fugitive#Complete(a:A, b:git_dir)
endif
endfunction