Provide FugitiveGenerate() and FugitiveParse()

This commit is contained in:
Tim Pope 2018-07-22 01:29:49 -04:00
parent 1e41a88ec9
commit 71acb7da35
2 changed files with 38 additions and 20 deletions

View File

@ -305,17 +305,17 @@ function! s:repo_bare() dict abort
endif endif
endfunction endfunction
function! s:repo_translate(spec) dict abort function! s:repo_translate(spec, ...) dict abort
let rev = a:spec let rev = a:spec
let dir = self.git_dir let dir = self.git_dir
let tree = FugitiveTreeForGitDir(dir) let tree = FugitiveTreeForGitDir(dir)
if rev ==# '.' || rev ==# '/.' if rev ==# '.'
let f = empty(tree) ? dir : tree let f = empty(tree) ? dir : tree
elseif rev =~# '^/\=\.git$' && empty(tree) elseif rev =~# '^/\=\.git$' && empty(tree)
let f = dir let f = dir
elseif rev =~# '^/\=\.git/' elseif rev =~# '^/\=\.git/'
let f = dir . s:sub(rev, '^/=\.git', '') let f = dir . s:sub(rev, '^/=\.git', '')
elseif empty(rev) elseif empty(rev) || rev ==# '/.'
return self.tree() return self.tree()
elseif rev =~# '^/' elseif rev =~# '^/'
let f = self.tree(rev) let f = self.tree(rev)
@ -355,7 +355,11 @@ function! s:repo_translate(spec) dict abort
endif endif
endif endif
endif endif
return f return a:0 && a:1 ? s:PlatformSlash(f) : f
endfunction
function! s:Generate(rev) abort
return s:repo().translate(a:rev, 1)
endfunction endfunction
function! s:repo_head(...) dict abort function! s:repo_head(...) dict abort
@ -1466,11 +1470,11 @@ function! s:Grep(cmd,bang,arg) abort
let list = a:cmd =~# '^l' ? getloclist(0) : getqflist() let list = a:cmd =~# '^l' ? getloclist(0) : getqflist()
for entry in list for entry in list
if bufname(entry.bufnr) =~ ':' if bufname(entry.bufnr) =~ ':'
let entry.filename = s:repo().translate(bufname(entry.bufnr)) let entry.filename = s:Generate(bufname(entry.bufnr))
unlet! entry.bufnr unlet! entry.bufnr
let changed = 1 let changed = 1
elseif a:arg =~# '\%(^\| \)--cached\>' elseif a:arg =~# '\%(^\| \)--cached\>'
let entry.filename = s:repo().translate(':0:'.bufname(entry.bufnr)) let entry.filename = s:Generate(':0:'.bufname(entry.bufnr))
unlet! entry.bufnr unlet! entry.bufnr
let changed = 1 let changed = 1
endif endif
@ -1620,7 +1624,7 @@ function! s:Edit(cmd, bang, mods, ...) abort
let file = buffer.relative('/') let file = buffer.relative('/')
endif endif
try try
let file = buffer.repo().translate(file) let file = s:Generate(file)
catch /^fugitive:/ catch /^fugitive:/
return 'echoerr v:errmsg' return 'echoerr v:errmsg'
endtry endtry
@ -1693,14 +1697,14 @@ function! s:Write(force,...) abort
return 'echoerr '.string('fugitive: cannot determine file path') return 'echoerr '.string('fugitive: cannot determine file path')
endif endif
if path =~# '^:\d\>' if path =~# '^:\d\>'
return 'write'.(a:force ? '! ' : ' ').s:fnameescape(s:repo().translate(s:buffer().expand(path))) return 'write'.(a:force ? '! ' : ' ').s:fnameescape(s:Generate(s:buffer().expand(path)))
endif endif
let always_permitted = (s:buffer().relative() ==# path && s:buffer().commit() =~# '^0\=$') let always_permitted = (s:buffer().relative() ==# 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) !=# '' 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)' let v:errmsg = 'fugitive: file has uncommitted changes (use ! to override)'
return 'echoerr v:errmsg' return 'echoerr v:errmsg'
endif endif
let file = s:repo().translate(path) let file = s:Generate(path)
let treebufnr = 0 let treebufnr = 0
for nr in range(1,bufnr('$')) for nr in range(1,bufnr('$'))
if fnamemodify(bufname(nr),':p') ==# file if fnamemodify(bufname(nr),':p') ==# file
@ -1740,7 +1744,7 @@ function! s:Write(force,...) abort
call writefile(readfile(temp,'b'),file,'b') call writefile(readfile(temp,'b'),file,'b')
endif endif
else else
execute 'write! '.s:fnameescape(s:repo().translate(path)) execute 'write! '.s:fnameescape(s:Generate(path))
endif endif
if a:force if a:force
@ -1756,9 +1760,9 @@ function! s:Write(force,...) abort
set nomodified set nomodified
endif endif
let one = s:repo().translate(':1:'.path) let one = s:Generate(':1:'.path)
let two = s:repo().translate(':2:'.path) let two = s:Generate(':2:'.path)
let three = s:repo().translate(':3:'.path) let three = s:Generate(':3:'.path)
for nr in range(1,bufnr('$')) for nr in range(1,bufnr('$'))
let name = fnamemodify(bufname(nr), ':p') let name = fnamemodify(bufname(nr), ':p')
if bufloaded(nr) && !getbufvar(nr,'&modified') && (name ==# one || name ==# two || name ==# three) if bufloaded(nr) && !getbufvar(nr,'&modified') && (name ==# one || name ==# two || name ==# three)
@ -1767,7 +1771,7 @@ function! s:Write(force,...) abort
endfor endfor
unlet! restorewinnr unlet! restorewinnr
let zero = s:repo().translate(':0:'.path) let zero = s:Generate(':0:'.path)
silent execute 'doautocmd BufWritePost' s:fnameescape(zero) silent execute 'doautocmd BufWritePost' s:fnameescape(zero)
for tab in range(1,tabpagenr('$')) for tab in range(1,tabpagenr('$'))
for winnr in range(1,tabpagewinnr(tab,'$')) for winnr in range(1,tabpagewinnr(tab,'$'))
@ -1978,12 +1982,12 @@ function! s:Diff(vert,keepfocus,...) abort
elseif (empty(args) || args[0] ==# ':') && s:buffer().commit() =~# '^[0-1]\=$' && s:repo().git_chomp_in_tree('ls-files', '--unmerged', '--', s:buffer().relative()) !=# '' elseif (empty(args) || args[0] ==# ':') && s:buffer().commit() =~# '^[0-1]\=$' && s:repo().git_chomp_in_tree('ls-files', '--unmerged', '--', s:buffer().relative()) !=# ''
let vert = empty(a:vert) ? s:diff_modifier(3) : a:vert let vert = empty(a:vert) ? s:diff_modifier(3) : a:vert
let nr = bufnr('') let nr = bufnr('')
execute 'leftabove '.vert.'split' s:fnameescape(fugitive#repo().translate(s:buffer().expand(':2'))) execute 'leftabove '.vert.'split' s:fnameescape(s:Generate(s:buffer().relative(':2:')))
execute 'nnoremap <buffer> <silent> dp :diffput '.nr.'<Bar>diffupdate<CR>' execute 'nnoremap <buffer> <silent> dp :diffput '.nr.'<Bar>diffupdate<CR>'
let nr2 = bufnr('') let nr2 = bufnr('')
call s:diffthis() call s:diffthis()
wincmd p wincmd p
execute 'rightbelow '.vert.'split' s:fnameescape(fugitive#repo().translate(s:buffer().expand(':3'))) execute 'rightbelow '.vert.'split' s:fnameescape(s:Generate(s:buffer().relative(':3:')))
execute 'nnoremap <buffer> <silent> dp :diffput '.nr.'<Bar>diffupdate<CR>' execute 'nnoremap <buffer> <silent> dp :diffput '.nr.'<Bar>diffupdate<CR>'
let nr3 = bufnr('') let nr3 = bufnr('')
call s:diffthis() call s:diffthis()
@ -2016,7 +2020,7 @@ function! s:Diff(vert,keepfocus,...) abort
let file = s:buffer().relative(empty(s:buffer().commit()) ? ':0:' : '/') let file = s:buffer().relative(empty(s:buffer().commit()) ? ':0:' : '/')
endif endif
try try
let spec = s:repo().translate(file) let spec = s:Generate(file)
let restore = s:diff_restore() let restore = s:diff_restore()
if exists('+cursorbind') if exists('+cursorbind')
setlocal cursorbind setlocal cursorbind
@ -2076,7 +2080,7 @@ function! s:Move(force, rename, destination) abort
return 'keepalt saveas! '.s:fnameescape(destination) return 'keepalt saveas! '.s:fnameescape(destination)
endif endif
else else
return 'file '.s:fnameescape(s:repo().translate(':0:'.destination)) return 'file '.s:fnameescape(s:Generate(':0:'.destination))
endif endif
endfunction endfunction
@ -2442,7 +2446,7 @@ function! s:Browse(bang,line1,count,...) abort
if filereadable(s:repo().dir('refs/tags/' . expanded)) if filereadable(s:repo().dir('refs/tags/' . expanded))
let expanded = '.git/refs/tags/' . expanded let expanded = '.git/refs/tags/' . expanded
endif endif
let full = s:repo().translate(expanded) let full = s:Generate(expanded)
let commit = '' let commit = ''
if full =~? '^fugitive:' if full =~? '^fugitive:'
let [dir, commit, path] = s:DirCommitFile(full) let [dir, commit, path] = s:DirCommitFile(full)
@ -3244,7 +3248,7 @@ function! fugitive#Cfile() abort
elseif len(results) > 1 elseif len(results) > 1
let pre = '+' . join(map(results[1:-1], 'escape(v:val, " ")'), '\|') . ' ' let pre = '+' . join(map(results[1:-1], 'escape(v:val, " ")'), '\|') . ' '
endif endif
return pre . s:fnameescape(fugitive#repo().translate(results[0])) return pre . s:fnameescape(s:Generate(results[0]))
endfunction endfunction
function! fugitive#cfile() abort function! fugitive#cfile() abort

View File

@ -152,6 +152,20 @@ function! FugitiveReal(...) abort
return call('FugitivePath', a:000) return call('FugitivePath', a:000)
endfunction endfunction
function! FugitiveGenerate(...) abort
return fugitive#repo(a:0 > 1 ? a:2 : get(b:, 'git_dir', '')).translate(a:0 ? a:1 : '', 1)
endfunction
function! FugitiveParse(...) abort
let path = s:shellslash(a:0 ? a:1 : @%)
let vals = matchlist(path, '\c^fugitive:\%(//\)\=\(.\{-\}\)\%(//\|::\)\(\x\{40\}\|[0-3]\)\(/.*\)\=$')
if len(vals)
return [(vals[2] =~# '^.$' ? ':' : '') . vals[2] . substitute(vals[3], '^/', ':', ''), vals[1]]
endif
let v:errmsg = 'fugitive: invalid Fugitive URL ' . path
throw v:errmsg
endfunction
augroup fugitive augroup fugitive
autocmd! autocmd!