module Repobrowse::GitPatch

included by Repobrowse::Git

Public Instance Methods

patch(r, repo, objid) click to toggle source

/$REPO_NAME/$HEX.patch

# File lib/repobrowse/git_patch.rb, line 14
def patch(r, repo, objid)
  rgd = repo.driver.rugged
  cmt = rgd.rev_parse("#{objid}^{commit}") rescue nil
  return r404(r) unless Rugged::Commit === cmt
  time = cmt.author[:time]
  cmt = cmt.oid

  # disambiguate, expand abbreviated commit IDs to be cache-friendly
  if objid != cmt
    loc = r.base_url
    loc << "#{r.script_name}/#{repo.name}/#{cmt}.patch"
    return r.redirect(loc)
  end

  # command should match signature, so not using rugged, here;
  # and mboxrd support is fairly recent in git.git.  rugged/libgit2
  # developers also do not use an email+patch-driven workflow, so I
  # don't expect it to support patch formatting as well as git.git does
  begin
    cmd = %W(format-patch -M --stdout --encoding=utf8 -1 #{cmt})
    mboxrd = @@mboxrd and cmd << mboxrd
    cmd << "--signature=git #{cmd.join(' ')}"
    io = repo.driver.popen(cmd)
    if buf = io.read(0x2000)
      h = {
        'Content-Type' => 'text/plain; charset=UTF-8',
        'Last-Modified' => (time || Time.now).httpdate,
        'Expires' => (Time.now + 604800).httpdate,
        'Content-Disposition' => %Q{inline; filename="#{cmt}.patch"},
      }
      return r.halt [ 200, h, Repobrowse::PipeBody.new(io, buf) ]
    end
    io.close
    if mboxrd
      @@mboxrd = nil
    else
      return r_err(r, 'Internal Server Error')
    end
  end while true
end