Better HTTP redirect detection

These HTTP headers may have other :GBrowse applications, so if we're
parsing them, we may as well hang onto them.
This commit is contained in:
Tim Pope
2021-08-29 16:30:14 -04:00
parent dfd7be2294
commit 6b546f37d0

View File

@@ -918,6 +918,8 @@ function! fugitive#RevParse(rev, ...) abort
throw 'fugitive: failed to parse revision ' . a:rev throw 'fugitive: failed to parse revision ' . a:rev
endfunction endfunction
" Section: Git config
function! s:ConfigTimestamps(dir, dict) abort function! s:ConfigTimestamps(dir, dict) abort
let files = ['/etc/gitconfig', '~/.gitconfig', let files = ['/etc/gitconfig', '~/.gitconfig',
\ len($XDG_CONFIG_HOME) ? $XDG_CONFIG_HOME . '/git/config' : '~/.config/git/config'] \ len($XDG_CONFIG_HOME) ? $XDG_CONFIG_HOME . '/git/config' : '~/.config/git/config']
@@ -1168,7 +1170,39 @@ function! fugitive#SshHostAlias(authority) abort
return (len(user) ? user . '@' : '') . get(c, 'hostname', host) . (port =~# '^\%(22\)\=$' ? '' : ':' . port) return (len(user) ? user . '@' : '') . get(c, 'hostname', host) . (port =~# '^\%(22\)\=$' ? '' : ':' . port)
endfunction endfunction
let s:redirects = {} function! s:CurlResponse(result) abort
let a:result.headers = {}
for line in a:result.exit_status ? [] : remove(a:result, 'stdout')
let header = matchlist(line, '^\([[:alnum:]-]\+\):\s\(.\{-\}\)'. "\r\\=$")
if len(header)
let k = tolower(header[1])
if has_key(a:result.headers, k)
let a:result.headers[k] .= ', ' . header[2]
else
let a:result.headers[k] = header[2]
endif
elseif empty(line)
break
endif
endfor
endfunction
let s:remote_headers = {}
function! fugitive#RemoteHttpHeaders(remote) abort
if a:remote !~# '^https\=://.' || !s:executable('curl')
return {}
endif
if !has_key(s:remote_headers, a:remote)
let url = a:remote . '/info/refs?service=git-upload-pack'
let exec = s:JobExecute(
\ ['curl', '--disable', '--silent', '--max-time', '5', '-X', 'GET', '-I',
\ url], {}, [function('s:CurlResponse')], {})
call fugitive#Wait(exec)
let s:remote_headers[a:remote] = exec.headers
endif
return s:remote_headers[a:remote]
endfunction
function! fugitive#ResolveRemote(remote) abort function! fugitive#ResolveRemote(remote) abort
let scp_authority = matchstr(a:remote, '^[^:/]\+\ze:\%(//\)\@!') let scp_authority = matchstr(a:remote, '^[^:/]\+\ze:\%(//\)\@!')
@@ -1182,15 +1216,11 @@ function! fugitive#ResolveRemote(remote) abort
elseif authority !~# ':' elseif authority !~# ':'
return authority . ':' . path return authority . ':' . path
endif endif
elseif a:remote =~# '^https\=://' && s:executable('curl') elseif a:remote =~# '^https\=://'
if !has_key(s:redirects, a:remote) let headers = fugitive#RemoteHttpHeaders(a:remote)
let s:redirects[a:remote] = matchstr(join(s:JobExecute( let loc = matchstr(get(headers, 'location', ''), '^https\=://.\{-\}\ze/info/refs?')
\ ['curl', '--disable', '--silent', '--max-time', '5', '-I', if len(loc)
\ a:remote . '/info/refs?service=git-upload-pack'], {}, [], {}).stdout, "\n"), return loc
\ 'Location: \zs\S\+\ze/info/refs?')
endif
if len(s:redirects[a:remote])
return s:redirects[a:remote]
endif endif
elseif a:remote =~# '^ssh://' elseif a:remote =~# '^ssh://'
let authority = matchstr(a:remote, '[^/?#]*', 6) let authority = matchstr(a:remote, '[^/?#]*', 6)
@@ -7125,7 +7155,11 @@ function! fugitive#BrowseCommand(line1, count, range, bang, mods, arg, args) abo
if empty(remote) || remote ==# '.' if empty(remote) || remote ==# '.'
let remote = s:Remote(dir) let remote = s:Remote(dir)
endif endif
let remote_url = fugitive#RemoteUrl(remote, dir) if remote =~# ':'
let remote_url = remote
else
let remote_url = fugitive#RemoteUrl(remote, dir)
endif
let raw = empty(remote_url) ? remote : remote_url let raw = empty(remote_url) ? remote : remote_url
let git_dir = s:GitDir(dir) let git_dir = s:GitDir(dir)