Handle URL-unsafe characters in :GBrowse API

Of the 8 :GBrowse providers listed in the README, 7 make no attempt to
handle URL encoding.  So it makes sense for Fugitive to take
responsibility for this.  By transposing "%" and "~" in API parameters
and then reversing the process on the generated URL, we can accommodate
both usages.  This is transitional and will later be ditched in favor of
straightforward URL encoding.

References: https://github.com/cedarbaum/fugitive-azure-devops.vim/issues/3
This commit is contained in:
Tim Pope
2022-06-26 16:02:07 -04:00
parent 224b65ef58
commit 8fd6bad4a4

View File

@@ -7243,7 +7243,9 @@ augroup END
" Section: :GBrowse " Section: :GBrowse
function! s:BrowserOpen(url, mods, echo_copy) abort function! s:BrowserOpen(url, mods, echo_copy) abort
let url = substitute(a:url, '[ <>\|"]', '\="%".printf("%02X",char2nr(submatch(0)))', 'g') let [_, main, query, anchor; __] = matchlist(a:url, '^\([^#?]*\)\(?[^#]*\)\=\(#.*\)\=')
let url = main . tr(query, ' ', '+') . anchor
let url = substitute(url, '[ <>\|"]', '\="%".printf("%02X",char2nr(submatch(0)))', 'g')
let mods = s:Mods(a:mods) let mods = s:Mods(a:mods)
if a:echo_copy if a:echo_copy
if has('clipboard') if has('clipboard')
@@ -7476,28 +7478,30 @@ function! fugitive#BrowseCommand(line1, count, range, bang, mods, arg, ...) abor
\ 'repo': {'git_dir': git_dir}, \ 'repo': {'git_dir': git_dir},
\ 'remote': raw, \ 'remote': raw,
\ 'remote_name': remote, \ 'remote_name': remote,
\ 'commit': commit, \ 'commit': s:UrlEncode(commit),
\ 'path': path, \ 'path': substitute(s:UrlEncode(path), '%20', ' ', 'g'),
\ 'type': type, \ 'type': type,
\ 'line1': line1, \ 'line1': line1,
\ 'line2': line2} \ 'line2': line2}
if empty(path) if empty(path)
if type ==# 'ref' && ref =~# '^refs/' if type ==# 'ref' && ref =~# '^refs/'
let opts.path = '.git/' . ref let opts.path = '.git/' . s:UrlEncode(ref)
let opts.type = '' let opts.type = ''
elseif type ==# 'root' elseif type ==# 'root'
let opts.path ='.git/index' let opts.path ='.git/index'
let opts.type = '' let opts.type = ''
endif endif
elseif type ==# 'tree' && !empty(path) elseif type ==# 'tree' && !empty(path)
let opts.path = s:sub(path, '/\=$', '/') let opts.path = s:sub(opts.path, '/\=$', '/')
endif endif
let opts.path = tr(substitute(opts.path, '\~', '%7E', 'g'), '%', '~')
let opts.commit = tr(substitute(opts.commit, '\~', '%7E', 'g'), '%', '~')
for l:.Handler in get(g:, 'fugitive_browse_handlers', []) for l:.Handler in get(g:, 'fugitive_browse_handlers', [])
let l:.url = call(Handler, [copy(opts)]) let l:.url = call(Handler, [copy(opts)])
if type(url) == type('') && url =~# '://' if type(url) == type('') && url =~# '://'
return s:BrowserOpen(url, a:mods, a:bang) return s:BrowserOpen(substitute(tr(url, '~', '%'), '\C%7E', '\~', 'g'), a:mods, a:bang)
endif endif
endfor endfor