Rails Rugged::Repository returning an empty repository

43 views Asked by At
  def serve_git_repo(temp_dir)
    repo = Rugged::Repository.new(temp_dir)

    response.headers["Vary"] = "Accept"
    response.headers["Connection"] = "keep-alive"
    response.headers["Content-Type"] = "application/octet-stream"

    response.stream.write("")

    walker = Rugged::Walker.new(repo)
    walker.push(repo.head.target_id)

    walker.each do |commit|
      commit.tree.walk_blobs do |root, entry|
        blob = repo.lookup(entry[:oid])

        StringIO.new(blob.content).each(8000) do |chunk|
          response.stream.write(chunk)
        end
      end
    end
  ensure
    response.stream.close
  end

With the above code when I git clone http://localhost:3000/git/serve_repo.git the code does clone the repo into the temp_dir, however, the walker serves me a empty repo with just a .git dir.

Any suggestions on how to get the response to stream the full repo? I'll be rewriting the git main later.

For context the plan here is that I'll provide a hashed url to a private repository, something akin to git clone https://example.com/4f404c1370fddb6a93fa0c2879f7c23f39a7e94f4dca46d85b2194cede641847.git asset where a user gets a read only access to this private repo.

1

There are 1 answers

0
disanv On

Maybe use a simpler Walker version to extract only what you want

require 'rugged'

repo_path = './my_git_repo'
repo = Rugged::Repository.new(repo_path)

walker = Rugged::Walker.new(repo)
walker.sorting(Rugged::SORT_TOPO | Rugged::SORT_REVERSE)
walker.push(repo.head.target_id)

walker.each do |commit|
  puts "Commit: #{commit.oid} - #{commit.message}"
  commit.tree.each_blob do |blob|
    puts "  File: #{blob[:name]}"
    puts "  Content:"
    puts repo.lookup(blob[:oid]).content
  end
end

I use each_blob to make it as simple as possible. Just to be sure what you mean by "empty repo with just a .git dir", there is nothing to interact with in .git ?