2

git リポジトリ内の特定のファイルについて、ファイルが変更された最後のコミットの SHA とタイムスタンプを調べたいと思います。

コマンドラインでは、このデータは特定のファイル パスの git log で表示されます。

git log -n 1 path/to/file

Ruby の「git」gem を使用すると、次のこともできます。

require 'git'
g = Git.open("/path/to/repo")
modified = g.log(1).object(relative/path/to/file).first.date
sha = g.log(1).object(relative/path/to/file).first.sha

これは素晴らしいことですが、多くのパスをループすると、実行速度が遅すぎます。Rugged は代わりに C ライブラリを使用するため、高速になることを期待していましたが、Rugged 構文で正しいクエリを作成する方法がわかりません。助言がありますか?

4

1 に答える 1

9

これはうまくいくはずです:

repo = Rugged::Repository.new("/path/to/repo")
walker = Rugged::Walker.new(repo)
walker.sorting(Rugged::SORT_DATE)
walker.push(repo.head.target)
commit = walker.find do |commit|
  commit.parents.size == 1 && commit.diff(paths: ["relative/path/to/file"]).size > 0
end
sha = commit.oid

https://github.com/libgit2/pygit2/issues/200#issuecomment-15899713から取得および適応

余談ですが、 rugged が C で書かれているからといって、コストのかかる操作が突然安価で迅速になるわけではありません。明らかに、多くの文字列解析などを節約できますが、これが常にボトルネックになるとは限りません。

ここでは実際のテキストの diff には興味がないので、libgit2GIT_DIFF_FORCE_BINARYはこのルックアップのパフォーマンスを向上させるのにも役立つ可能性があります。

Rugged リポジトリ自体でこれをテストすると、正しく動作します。

repo = Rugged::Repository.new(".")
walker = Rugged::Walker.new(repo)
walker.sorting(Rugged::SORT_DATE)
walker.push(repo.head.target)
commit = walker.find do |commit|
  commit.parents.size == 1 && commit.diff(paths: ["Gemfile"]).size > 0
end
sha = commit.oid # => "8f5c763377f5bf0fb88d196b7c45a7d715264ad4"

walker = Rugged::Walker.new(repo)
walker.sorting(Rugged::SORT_DATE)
walker.push(repo.head.target)
commit = walker.find do |commit|
  commit.parents.size == 1 && commit.diff(paths: [".travis.yml"]).size > 0
end
sha = commit.oid # => "4e18e05944daa2ba8d63a2c6b149900e3b93a88f"
于 2014-01-23T11:30:14.227 に答える