2014-01-23 4 views
1

Для данного файла в git-репо я хотел бы посмотреть SHA последнего коммита, в котором был изменен файл, вместе с меткой времени.Доступ к данным журнала git с использованием рубинового прочного драгоценного камня?

В командной строке эти данные отображаются в журнале git для определенного пути к файлу, например.

git log -n 1 path/to/file 

Используя «GIT» драгоценный камень рубин Я также могу это сделать:

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 вместо этого, я надеялся, что это будет быстрее, но не может понять, как построить правильный запрос в прочном синтаксисе. Какие-либо предложения?

ответ

8

Это должно работать:

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

Как и в сторону: Просто потому, что прочный написан на С, не означает, что дорогостоящие операции вдруг стали дешевы и быстро. Очевидно, что вы сохраняете много синтаксического анализа строк и тому подобное, но это не всегда является узким местом.

Как вы не заинтересованы в фактическом текстовом различии здесь, libgit2 GIT_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" 
+0

Спасибо! Хм, не уверен, что я пропустил, но, похоже, не работает для меня - 'commit' выходит как' nil'. Также мне кажется странным, что синтаксис требует этого цикла, потому что ни один из методов в моем вопросе не требует (явного) цикла, но вместо этого запрашивает журнал ... – cboettig

+0

Я просто обновил свой ответ с помощью крошечных исправлений (теперь он использует правильная сортировка и игнорирование слияния). –

+0

Я также добавил несколько примеров. Убедитесь, что путь, который вы передаете 'Rugged :: Commit # diff', действительно существует в вашем репо, что может объяснить ваше значение nil' commit. Кроме того, вы можете передать 'disable_pathspec_match: true', если вы передаете только фиксированные пути, а не pathspecs в метод' # diff'. –