diff --git a/autoload/fugitive.vim b/autoload/fugitive.vim index fc30676..563b8d9 100644 --- a/autoload/fugitive.vim +++ b/autoload/fugitive.vim @@ -1240,29 +1240,40 @@ endfunction function! s:UrlParse(url) abort let scp_authority = matchstr(a:url, '^[^:/]\+\ze:\%(//\)\@!') if len(scp_authority) && !(has('win32') && scp_authority =~# '^\a:[\/]') - let url = {'scheme': 'ssh', 'authority': scp_authority, - \ 'path': strpart(a:url, len(scp_authority) + 1)} + let url = {'scheme': 'ssh', 'authority': scp_authority, 'hash': '', + \ 'path': substitute(strpart(a:url, len(scp_authority) + 1), '[#?]', '\=printf("%%%02X", char2nr(submatch(0)))', 'g')} elseif empty(a:url) - let url = {'scheme': '', 'authority': '', 'path': ''} + let url = {'scheme': '', 'authority': '', 'path': '', 'hash': ''} else - let match = matchlist(a:url, '^\([[:alnum:].+-]\+\)://\([^/]*\)\(/.*\)\=\%(#\|$\)') + let match = matchlist(a:url, '^\([[:alnum:].+-]\+\)://\([^/]*\)\(/[^#]*\)\=\(#.*\)\=$') if empty(match) - let url = {'scheme': 'file', 'authority': '', 'path': a:url} + let url = {'scheme': 'file', 'authority': '', 'hash': '', + \ 'path': substitute(a:url, '[#?]', '\=printf("%%%02X", char2nr(submatch(0)))', 'g')} else - let url = {'scheme': match[1], 'authority': match[2]} + let url = {'scheme': match[1], 'authority': match[2], 'hash': match[4]} let url.path = empty(match[3]) ? '/' : match[3] endif endif if (url.scheme ==# 'ssh' || url.scheme ==# 'git') && url.path[0:1] ==# '/~' let url.path = strpart(url.path, 1) endif + if url.path =~# '^/' + let url.href = url.scheme . '://' . url.authority . url.path . url.hash + elseif url.path =~# '^\~' + let url.href = url.scheme . '://' . url.authority . '/' . url.path . url.hash + elseif url.scheme ==# 'ssh' && url.authority !~# ':' + let url.href = url.authority . ':' . url.path . url.hash + else + let url.href = a:url + endif + let url.url = matchstr(url.href, '^[^#]*') return url endfunction function! s:RemoteResolve(url, flags) abort let remote = s:UrlParse(a:url) if remote.scheme =~# '^https\=$' && index(a:flags, ':nohttp') < 0 - let headers = fugitive#RemoteHttpHeaders(remote.scheme . '://' . remote.authority . remote.path) + let headers = fugitive#RemoteHttpHeaders(remote.url) let loc = matchstr(get(headers, 'location', ''), '^https\=://.\{-\}\ze/info/refs?') if len(loc) let remote = s:UrlParse(loc) @@ -1312,15 +1323,6 @@ function! s:RemoteCallback(config, into, flags, cb) abort let a:into.host = substitute(a:into.authority, '.\{-\}@', '', '') let a:into.hostname = substitute(a:into.host, ':\d\+$', '', '') let a:into.port = matchstr(a:into.host, ':\zs\d\+$', '', '') - if a:into.path =~# '^/' - let a:into.url = a:into.scheme . '://' . a:into.authority . a:into.path - elseif a:into.path =~# '^\~' - let a:into.url = a:into.scheme . '://' . a:into.authority . '/' . a:into.path - elseif a:into.scheme ==# 'ssh' && a:into.authority !~# ':' - let a:into.url = a:into.authority . ':' . a:into.path - else - let a:into.url = url - endif if len(a:cb) call call(a:cb[0], [a:into] + a:cb[1:-1]) endif