From 6b546f37d04f4598fc2f7cd273f709158a78bc88 Mon Sep 17 00:00:00 2001 From: Tim Pope Date: Sun, 29 Aug 2021 16:30:14 -0400 Subject: [PATCH] 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. --- autoload/fugitive.vim | 56 ++++++++++++++++++++++++++++++++++--------- 1 file changed, 45 insertions(+), 11 deletions(-) diff --git a/autoload/fugitive.vim b/autoload/fugitive.vim index 496a378..6da79bd 100644 --- a/autoload/fugitive.vim +++ b/autoload/fugitive.vim @@ -918,6 +918,8 @@ function! fugitive#RevParse(rev, ...) abort throw 'fugitive: failed to parse revision ' . a:rev endfunction +" Section: Git config + function! s:ConfigTimestamps(dir, dict) abort let files = ['/etc/gitconfig', '~/.gitconfig', \ 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) 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 let scp_authority = matchstr(a:remote, '^[^:/]\+\ze:\%(//\)\@!') @@ -1182,15 +1216,11 @@ function! fugitive#ResolveRemote(remote) abort elseif authority !~# ':' return authority . ':' . path endif - elseif a:remote =~# '^https\=://' && s:executable('curl') - if !has_key(s:redirects, a:remote) - let s:redirects[a:remote] = matchstr(join(s:JobExecute( - \ ['curl', '--disable', '--silent', '--max-time', '5', '-I', - \ a:remote . '/info/refs?service=git-upload-pack'], {}, [], {}).stdout, "\n"), - \ 'Location: \zs\S\+\ze/info/refs?') - endif - if len(s:redirects[a:remote]) - return s:redirects[a:remote] + elseif a:remote =~# '^https\=://' + let headers = fugitive#RemoteHttpHeaders(a:remote) + let loc = matchstr(get(headers, 'location', ''), '^https\=://.\{-\}\ze/info/refs?') + if len(loc) + return loc endif elseif a:remote =~# '^ssh://' 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 ==# '.' let remote = s:Remote(dir) 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 git_dir = s:GitDir(dir)