Поиск шаблона с помощью регулярного выражения и libgit2

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

git grep -G pattern revision

Это работает просто отлично, но проблема в том, что я делаю это в цикле, и это очень медленно. Я профилировал код в Linux, и один только вызов __libc_fork занимает 94% времени выполнения.

Очевидно, я хотел бы избежать этих ненужных накладных расходов. Для выполнения некоторых других операций с git я уже использую libgit2 в своем приложении, но я не вижу удобного способа выполнять поиск по регулярному выражению, как с git grep. Я могу представить вручную просмотр всех файлов, связанных с фиксацией, и выполнение поиска, но я надеялся на более элегантное решение, до нескольких строк.

Мне не хватает соответствующего API libgit2? Кто-нибудь знает быстрый способ поиска шаблона с помощью libgit2?

EDIT Просто для уточнения: в моем цикле ревизия фиксируется, но меняется шаблон.


person Dimitar Asenov    schedule 27.04.2016    source источник
comment
Похоже, вы ищете ревизию, в которой появился определенный текст. Вы можете использовать git log -S pattern или создать небольшой сценарий оболочки, который будет выходить из 1 или 0 в зависимости от того, нашел ли он то, что вы ищете, а затем использовать git bisect с этим сценарием.   -  person Carlos Campderrós    schedule 27.04.2016
comment
На самом деле это не так. У меня есть длинный список строк, и я точно знаю, что каждая строка появляется как часть какой-то строки в каком-то файле в конкретном коммите. Различные строки могут находиться в разных файлах. Мне нужно получить всю строку, в которой появляется каждая строка, потому что меня интересует другая часть той же строки. Так что git grep кажется подходящим инструментом для работы. Мне просто нужен более быстрый эквивалент libgit2, но я не хочу писать его с нуля.   -  person Dimitar Asenov    schedule 27.04.2016


Ответы (1)


libgit2 не имеет эквивалента git grep, так как это далеко не базовая операция Git. Это очень высокий уровень, и реальная интересная работа (эффективный grep) не имеет ничего общего с Git, поэтому libgit2 будет плохим местом для размещения этого кода.

Поскольку проблема, которую вы видите, сводится к тому, что разветвление стоит дороже, чем что-либо еще, я вижу два способа избежать этого. Один из них - использовать параметр --batch git cat-file, чтобы передать ему список объектов для отображения, который вы можете получить, например. от ls-tree нравится

git ls-tree -r ${revision} | cut -f 1 | cut -d ' ' -f 3 | git cat-file --batch

который производит машиночитаемый вывод с триплетом $id $type $len в начале каждого файла (может быть проще/дешевле заменить эти cut своим собственным кодом, который извлекает идентификаторы из потока, поступающего из ls-tree). Или вы можете использовать libgit2 для обхода дерева и рекурсивного захвата всех больших двоичных объектов из деревьев, что в конечном итоге приведет к получению той же информации немного другим способом.

Затем вы можете использовать какую-либо форму grep для запуска этих буферов. Ваш любимый язык программирования, вероятно, имеет реализацию pcre или привязки к этой библиотеке, в которую вы можете скормить эти файлы.

Вы должны иметь возможность передавать их по одному, независимо от того, какой метод извлечения вы выберете, читая только из cat-file по одному через те триплеты, которые предшествуют каждому объекту.

person Carlos Martín Nieto    schedule 29.04.2016
comment
Спасибо. Я подозревал, что libgit2 на самом деле не предоставляет то, что мне нужно напрямую. Я, скорее всего, выберу BLOB-объекты с помощью библиотеки. - person Dimitar Asenov; 02.05.2016