Techioz Blog

Rails Rugged::Repository が空のリポジトリを返す

概要

  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

上記のコードでは、 git clone http://localhost:3000/git/serve_repo.git を実行すると、コードはリポジトリを temp_dir にクローンしますが、ウォーカーは .git ディレクトリだけを含む空のリポジトリを提供します。

リポジトリ全体をストリーミングするための応答を取得する方法について何か提案はありますか?後で git main を書き換えます。

コンテキストとして、ここでの計画は、プライベート リポジトリにハッシュされた URL を提供することです。 git clone https://example.com/4f404c1370fddb6a93fa0c2879f7c23f39a7e94f4dca46d85b2194cede641847.git アセットに似ており、ユーザーはこのプライベート リポジトリへの読み取り専用アクセスを取得します。

解決策

必要なものだけを抽出するには、よりシンプルな Walker バージョンを使用するかもしれません

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

できるだけシンプルにするために each_blob を使用します。 「.git ディレクトリだけを含む空のリポジトリ」が何を意味するのかを確認するために、.git には操作するものは何もありません。