module Repobrowse::GitHTTPBackend
provides smart HTTP cloning for git repos
Public Instance Methods
git_http_backend_routes(r, repo)
click to toggle source
# File lib/repobrowse/git_http_backend.rb, line 80 def git_http_backend_routes(r, repo) r.is(path = 'git-upload-pack') { r.post { serve_smart(r, repo, path) } } r.is(path = 'info/refs') { # QUERY_STRING has exactly one parameter # See https://80x24.org/git/src/v2.16.1:Documentation/technical/http-protocol.txt if /\Aservice=git-\w+-pack\z/ =~ r.env['QUERY_STRING'] r.get { serve_smart(r, repo, path) } else static(r, -"#{repo.path}/#{path}", 'text/plain', nil) end } %w(HEAD cloneurl description objects/info/http-alternates objects/info/alternates objects/info/packs).each { |txt| r.is(txt) { static(r, -"#{repo.path}/#{txt}", 'text/plain', nil) } } r.is('objects', :git_x2, :git_x38) { |x2, x38| static(r, -"#{repo.path}/objects/#{x2}/#{x38}", 'application/x-git-loose-object') } [ :git_pack, 'application/x-git-packed-objects', :git_pack_idx, 'application/x-git-packed-objects-toc' ].each_slice(2) { |sym, type| r.is('objects/pack', :sym) { |o| static(r, -"#{repo.path}/objects/pack/#{o}", type) } } end
input_to_file(env)
click to toggle source
# File lib/repobrowse/git_http_backend.rb, line 32 def input_to_file(env) tmp = Tempfile.new('git-http-backend-in') tmp.unlink tmp.sync = true IO.copy_stream(env['rack.input'], tmp.to_io) tmp.rewind tmp end
run_http_backend(r, repo, path)
click to toggle source
# File lib/repobrowse/git_http_backend.rb, line 41 def run_http_backend(r, repo, path) penv = { 'GIT_HTTP_EXPORT_ALL' => '1', 'PATH_TRANSLATED' => -"#{repo.path}/#{path}", } env = r.env # GIT_COMMITTER_NAME, GIT_COMMITTER_EMAIL # may be set in the server-process and are passed as-is %w(QUERY_STRING REMOTE_USER REMOTE_ADDR HTTP_CONTENT_ENCODING CONTENT_TYPE SERVER_PROTOCOL REQUEST_METHOD).each do |k| v = env[k] and penv[k] = v end IO.popen(penv, %W(git http-backend), in: input_to_file(env)) rescue => e r_err(r, "E: #{e.message} (#{e.class}) on #{repo.path}") end
serve_smart(r, repo, path)
click to toggle source
returns undef if 403 so it falls back to dumb HTTP
# File lib/repobrowse/git_http_backend.rb, line 59 def serve_smart(r, repo, path) rd = run_http_backend(r, repo, path) code = 200 h = {} # parse CGI response headers case rd.gets when %r{\AStatus:\s+(\d+)}i code = $1.to_i when %r{\A([^:]+):\s*(.*)\r\n\z} h[-$1] = -$2 when "\r\n" break # headers done onto the body when nil rd.close r_err(r, "unexpected EOF on git http-backend in #{repo.path}") end while true r.halt [ code, h, EachWrap.new(rd) ] end