mirror of
https://github.com/tpope/vim-fugitive.git
synced 2025-11-13 05:43:52 -05:00
Rework ref handing in :GBrowse
This is still a garbage fire, but at least now the use of `.git/refs/` paths has been relegated to the public interface. This also fixes a lot of quirks, and hopefully doesn't introduce too many new ones.
This commit is contained in:
@@ -7275,26 +7275,25 @@ function! fugitive#BrowseCommand(line1, count, range, bang, mods, arg, ...) abor
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
let refdir = fugitive#Find('.git/refs', dir)
|
||||
for subdir in ['tags/', 'heads/', 'remotes/']
|
||||
if expanded !~# '^[./]' && filereadable(refdir . '/' . subdir . expanded)
|
||||
let expanded = '.git/refs/' . subdir . expanded
|
||||
endif
|
||||
endfor
|
||||
let full = s:Generate(expanded, dir)
|
||||
let commit = ''
|
||||
if full =~? '^fugitive:'
|
||||
let ref = ''
|
||||
let forbid_ref_as_commit = 0
|
||||
if full =~# '^fugitive:'
|
||||
let [dir, commit, path] = s:DirCommitFile(full)
|
||||
if commit =~# '^:\=\d$'
|
||||
if commit =~# '^\d\=$'
|
||||
let commit = ''
|
||||
endif
|
||||
if commit =~ '..'
|
||||
let type = s:TreeChomp(['cat-file','-t',commit.s:sub(path,'^/',':')], dir)
|
||||
let branch = matchstr(expanded, '^[^:]*')
|
||||
elseif empty(path) || path ==# '/'
|
||||
let type = 'tree'
|
||||
let type = path =~# '^/\=$' ? 'tree' : 'blob'
|
||||
else
|
||||
let type = 'blob'
|
||||
let ref_match = matchlist(expanded, '^\(@{\@!\|[^:~^@]\+\)\(:\%(//\)\@!\|[~^@]\|$\)')
|
||||
let ref = get(ref_match, 1, '')
|
||||
let forbid_ref_as_commit = ref =~# '^@\=$' || ref_match[2] !~# '^:\=$'
|
||||
if empty(path) && !forbid_ref_as_commit
|
||||
let type = 'ref'
|
||||
else
|
||||
let type = s:ChompDefault(empty(path) ? 'commit': 'blob',
|
||||
\ ['cat-file', '-t', commit . substitute(path, '^/', ':', '')], dir)
|
||||
endif
|
||||
endif
|
||||
let path = path[1:-1]
|
||||
elseif empty(s:Tree(dir))
|
||||
@@ -7302,47 +7301,41 @@ function! fugitive#BrowseCommand(line1, count, range, bang, mods, arg, ...) abor
|
||||
let type = ''
|
||||
else
|
||||
let path = fugitive#Path(full, '/')[1:-1]
|
||||
if path =~# '^\.git/'
|
||||
let type = ''
|
||||
elseif isdirectory(full) || empty(path)
|
||||
if empty(path) || isdirectory(full)
|
||||
let type = 'tree'
|
||||
else
|
||||
let type = 'blob'
|
||||
endif
|
||||
endif
|
||||
if type ==# 'tree' && !empty(path)
|
||||
let path = s:sub(path, '/\=$', '/')
|
||||
if path =~# '^\.git/'
|
||||
let ref = matchstr(path, '^.git/\zs\%(refs/[^/]\+/[^/].*\|\w*HEAD\)$')
|
||||
let type = empty(ref) ? 'root': 'ref'
|
||||
let path = ''
|
||||
endif
|
||||
let actual_dir = fugitive#Find('.git/', dir)
|
||||
if path =~# '^\.git/.*HEAD$' && filereadable(actual_dir . path[5:-1])
|
||||
let body = readfile(actual_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.*')
|
||||
if empty(ref) || ref ==# 'HEAD' || ref ==# '@'
|
||||
let ref = fugitive#Head(-1, dir)
|
||||
endif
|
||||
if ref =~# '^\x\{40,\}$'
|
||||
let ref = ''
|
||||
elseif !empty(ref) && ref !~# '^refs/'
|
||||
let ref = FugitiveExecute(['rev-parse', '--symbolic-full-name', ref], dir).stdout[0]
|
||||
if ref !~# '^refs/'
|
||||
let ref = ''
|
||||
endif
|
||||
endif
|
||||
|
||||
let merge = ''
|
||||
if path =~# '^\.git/refs/remotes/.'
|
||||
if empty(remote)
|
||||
let remote = matchstr(path, '^\.git/refs/remotes/\zs[^/]\+')
|
||||
let branch = matchstr(path, '^\.git/refs/remotes/[^/]\+/\zs.\+')
|
||||
else
|
||||
let merge = matchstr(path, '^\.git/refs/remotes/[^/]\+/\zs.\+')
|
||||
let branch = merge
|
||||
let path = '.git/refs/heads/'.merge
|
||||
endif
|
||||
elseif path =~# '^\.git/refs/heads/.'
|
||||
let branch = path[16:-1]
|
||||
elseif !exists('branch')
|
||||
let branch = FugitiveHead(0, dir)
|
||||
endif
|
||||
if !empty(branch)
|
||||
let r = FugitiveConfigGet('branch.'.branch.'.remote', config)
|
||||
let m = FugitiveConfigGet('branch.'.branch.'.merge', config)[11:-1]
|
||||
if !empty(remote) && ref =~# '^refs/remotes/[^/]\+/[^/]\|^refs/heads/[^/]'
|
||||
let merge = matchstr(ref, '^refs/\%(heads/\|remotes/[^/]\+/\)\zs.\+')
|
||||
let ref = 'refs/heads/' . merge
|
||||
elseif ref =~# '^refs/remotes/[^/]\+/[^/]'
|
||||
let remote = matchstr(ref, '^refs/remotes/\zs[^/]\+')
|
||||
let merge = matchstr(ref, '^refs/remotes/[^/]\+/\zs.\+')
|
||||
let ref = 'refs/heads/' . merge
|
||||
elseif ref =~# '^refs/heads/[^/]'
|
||||
let merge = strpart(ref, 11)
|
||||
let r = FugitiveConfigGet('branch.' . merge . '.remote', config)
|
||||
let m = FugitiveConfigGet('branch.' . merge . '.merge', config)[11:-1]
|
||||
if r ==# '.' && !empty(m)
|
||||
let r2 = FugitiveConfigGet('branch.'.m.'.remote', config)
|
||||
if r2 !~# '^\.\=$'
|
||||
@@ -7350,32 +7343,45 @@ function! fugitive#BrowseCommand(line1, count, range, bang, mods, arg, ...) abor
|
||||
let m = FugitiveConfigGet('branch.'.m.'.merge', config)[11:-1]
|
||||
endif
|
||||
endif
|
||||
if empty(remote)
|
||||
if r !~# '^\.\=$'
|
||||
let remote = r
|
||||
endif
|
||||
if r ==# '.' || r ==# remote
|
||||
let remote_ref = 'refs/remotes/' . remote . '/' . branch
|
||||
if !empty(remote)
|
||||
let remote_ref = 'refs/remotes/' . remote . '/' . merge
|
||||
if FugitiveConfigGet('push.default', config) ==# 'upstream' ||
|
||||
\ !filereadable(FugitiveFind('.git/' . remote_ref, dir)) && empty(s:ChompDefault('', ['rev-parse', '--verify', remote_ref, '--'], dir))
|
||||
let merge = m
|
||||
if path =~# '^\.git/refs/heads/.'
|
||||
let path = '.git/refs/heads/'.merge
|
||||
endif
|
||||
else
|
||||
let merge = branch
|
||||
let ref = 'refs/heads/' . merge
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
if empty(remote) || remote ==# '.'
|
||||
let remote = s:RemoteDefault(config)
|
||||
endif
|
||||
if empty(merge) || empty(remote)
|
||||
let provider_ref = ref
|
||||
else
|
||||
let provider_ref = 'refs/remotes/' . remote . '/' . merge
|
||||
endif
|
||||
if forbid_ref_as_commit || a:count >= 0
|
||||
let ref = ''
|
||||
if type ==# 'ref'
|
||||
let type = 'commit'
|
||||
endif
|
||||
elseif type ==# 'ref' && ref =~# '^refs/\%(heads\|tags\)/[^/]'
|
||||
let commit = matchstr(ref, '^\Crefs/\%(heads\|tags\)/\zs.*')
|
||||
endif
|
||||
|
||||
let line1 = a:count > 0 && type ==# 'blob' ? a:line1 : 0
|
||||
let line2 = a:count > 0 && type ==# 'blob' ? a:count : 0
|
||||
if empty(commit) && path !~# '^\.git/'
|
||||
if empty(commit) && type =~# '^\%(tree\|blob\)$'
|
||||
if a:count < 0
|
||||
let commit = merge
|
||||
elseif len(merge)
|
||||
let commit = matchstr(ref, '^\Crefs/\%(heads\|tags\)/\zs.*')
|
||||
elseif len(provider_ref)
|
||||
let owner = s:Owner(@%, dir)
|
||||
let commit = s:ChompDefault('', ['merge-base', 'refs/remotes/' . remote . '/' . merge, empty(owner) ? '@' : owner, '--'], dir)
|
||||
if line2 > 0 && empty(arg) && commit =~# '^\x\{40,\}$'
|
||||
let commit = s:ChompDefault('', ['merge-base', provider_ref, empty(owner) ? '@' : owner, '--'], dir)
|
||||
if line2 > 0 && empty(arg) && commit =~# '^\x\{40,\}$' && type ==# 'blob'
|
||||
let blame_list = tempname()
|
||||
call writefile([commit, ''], blame_list, 'b')
|
||||
let blame_cmd = ['-c', 'blame.coloring=none', 'blame', '-L', line1.','.line2, '-S', blame_list, '-s', '--show-number']
|
||||
@@ -7400,23 +7406,10 @@ function! fugitive#BrowseCommand(line1, count, range, bang, mods, arg, ...) abor
|
||||
endif
|
||||
endif
|
||||
if empty(commit)
|
||||
let commit = readfile(fugitive#Find('.git/HEAD', dir), '', 1)[0]
|
||||
let commit = fugitive#RevParse(empty(ref) ? 'HEAD' : ref, dir)
|
||||
endif
|
||||
let i = 0
|
||||
while commit =~# '^ref: ' && i < 10
|
||||
let ref_file = refdir[0 : -5] . commit[5:-1]
|
||||
if getfsize(ref_file) > 0
|
||||
let commit = readfile(ref_file, '', 1)[0]
|
||||
else
|
||||
let commit = fugitive#RevParse(commit[5:-1], dir)
|
||||
endif
|
||||
let i -= 1
|
||||
endwhile
|
||||
endif
|
||||
|
||||
if empty(remote) || remote ==# '.'
|
||||
let remote = s:RemoteDefault(config)
|
||||
endif
|
||||
if remote =~# ':'
|
||||
let remote_url = remote
|
||||
else
|
||||
@@ -7436,6 +7429,18 @@ function! fugitive#BrowseCommand(line1, count, range, bang, mods, arg, ...) abor
|
||||
\ 'line1': line1,
|
||||
\ 'line2': line2}
|
||||
|
||||
if empty(path)
|
||||
if type ==# 'ref' && ref =~# '^refs/'
|
||||
let opts.path = '.git/' . ref
|
||||
let opts.type = ''
|
||||
elseif type ==# 'root'
|
||||
let opts.path ='.git/index'
|
||||
let opts.type = ''
|
||||
endif
|
||||
elseif type ==# 'tree' && !empty(path)
|
||||
let opts.path = s:sub(path, '/\=$', '/')
|
||||
endif
|
||||
|
||||
let url = ''
|
||||
for Handler in get(g:, 'fugitive_browse_handlers', [])
|
||||
let url = call(Handler, [copy(opts)])
|
||||
|
||||
Reference in New Issue
Block a user